zoukankan      html  css  js  c++  java
  • 单例模式防反射及性能(二)

    单例模式的目的是创建一个对象,但是反射的方式,或者使用反序列的方式,就会对这种目的造成威胁,那么我们先来看看如何使用反射,如何使用反序列化,创建构造函数私有化的对象,以及我们如何防止反序列化创建对象。

    1.补充:如何选用单例模式

     (1)占用资源少,不需要延迟加载的,一般使用的是枚举和饿汉式,但是枚举比饿汉式安全。

     (2)占用资源大,需要延迟加载,一般使用静态内部类和懒汉式,静态内部类好于懒汉式,因为他更加的懒汉式、线程安全、调用的效率高。

    2.使用反射破解的时候,一般是不包括枚举的,所以他的安全性是恒爱的。

    3.方式一:反射破解

    package kw.test.sjms;
    
    import java.io.Serializable;
    
    /*
     * 懒汉式防止破解,原始单例程序
     */
    public class FDemoLH implements Serializable{
        private static FDemoLH instance ;
    
        private FDemoLH()
        {}
        
        public synchronized static FDemoLH  getinstance(){
            if(instance == null)
            {
                instance = new FDemoLH();
            }
            return instance;
        }
    }

    破解程序

    package kw.test.sjms;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.lang.reflect.Constructor;
    
    public class FClient {
        public static void main(String[] args) throws Exception {
          /*
           * 反射的方法调用私有的构造函数。
           */
            FDemoLH fDemoLH1 = FDemoLH.getinstance();
            FDemoLH fDemoLH2 = FDemoLH.getinstance();
            System.out.println(fDemoLH1 == fDemoLH2);
            
            String className = "kw.test.sjms.FClient";
            Class<FDemoLH> clazz = (Class<FDemoLH>)Class.forName("kw.test.sjms.FDemoLH");
            Constructor<FDemoLH> c= clazz.getDeclaredConstructor(null);
            c.setAccessible(true); //跳过检查
            FDemoLH fd1 = c.newInstance();
            FDemoLH fd2 = c.newInstance();
            
            System.out.println(fd1);
            System.out.println(fd2);
            
        }
    }

      方式二:反序列化破解

    package kw.test.sjms;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.lang.reflect.Constructor;
    
    public class FClient {
        public static void main(String[] args) throws Exception {        
            /*
             * 序列化
             */
            FDemoLH fDemoLH1 = FDemoLH.getinstance();
            System.out.println(fDemoLH1);
            FileOutputStream fileOutputStream = new FileOutputStream("D:/a.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fileOutputStream);
            oos.writeObject(fDemoLH1);
            oos.close();
            fileOutputStream.close();
            /*
             * 反序列化
             */
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/a.txt"));
            FDemoLH fDemoLH = (FDemoLH)ois.readObject();
            System.out.println(fDemoLH);
        }
    }

    其他的单例方式类似

    4.防止破解的方式

    package kw.test.sjms;
    
    import java.io.Serializable;
    
    /*
     * 懒汉式防止破解
     */
    public class FDemoLH implements Serializable{
        private static FDemoLH instance ;
    
        private FDemoLH()
        {}
        
        public synchronized static FDemoLH  getinstance(){
            if(instance == null)
            {
                instance = new FDemoLH();
            }
            return instance;
        }
        
        /*
         * 此方法是私有的,我尝试过公有,好像是不起作用的
         * */
        private Object readResolve()  
        {
            return instance;
        }
    }

    5.下来测试效率,模拟多线程,打印出每种方式占用的时间。或者使用CountDownLatch类,他是一个多线程的辅助类,观察其他线程有没有执行完。它的内部有一个计算器,当一个线程执行完了就会将计数器减一。Wait方法等待其他线程执行完。

    最终的结果是饿汉式最快、枚举、静态内部类、双重检测式、懒汉式依次变慢。

  • 相关阅读:
    Smart Client Architecture and Design Guide
    Duwamish密码分析篇, Part 3
    庆贺发文100篇
    .Net Distributed Application Design Guide
    New Introduction to ASP.NET 2.0 Web Parts Framework
    SPS toplevel Site Collection Administrators and Owners
    来自Ingo Rammer先生的Email关于《Advanced .Net Remoting》
    The newsletter published by Ingo Rammer
    深度探索.Net Remoting基础架构
    信道、接收器、接收链和信道接受提供程序
  • 原文地址:https://www.cnblogs.com/kw28188151/p/8548338.html
Copyright © 2011-2022 走看看