單例模式-反射攻擊的解決方案及原理分析


首先我們還是拿餓漢模式作為栗子進行測試,餓漢模式的代碼如下:

public class HungrySingleton implements Serializable {

    private static final HungrySingleton instance;

    static {
        instance = new HungrySingleton();
    }
    private HungrySingleton(){
    }

    public static HungrySingleton getInstance(){
        return instance;
    }

    private Object readResolve(){
        return instance;
    }

  1、先寫一個利用反射獲取實例的方法和直接獲取實例的方法,將兩者的返回值進行比較,看返回的是否是一個實例。

代碼如下:

public class Testreflection {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class object = HungrySingleton.class;
        Constructor constructor = object.getDeclaredConstructor();
        constructor.setAccessible(true);

        HungrySingleton instance = HungrySingleton.getInstance();
        HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();

        System.out.println(instance);
        System.out.println(newInstance);
        System.out.println(instance == newInstance);

     }
    }

  運行后的結果為:可見,兩者的結果並不是一個對象,則餓漢模式毅然受到了反射的攻擊。

 

2、那么改如何解決這反射攻擊呢?我們知道是在類加載的時候就加載了這個實例的,因為是在類加載的時候就生成了詞實例,那么我們可以在構造器里面加一個判斷,進行反射防御。代碼如下:

 

測試結果為:

這種方式有一個特點,也就是它對類加載這個時刻就把對象創建好的這種類是ok的,靜態內部類的單例也可以用。
對於不是靜態類的也需要解決下,要根據創建實例的順序進行解決。但是無論如何反射都可以訪問到類的方法和變量,進行修改,所以非
類加載這個時刻就把對象創建好的這種類,是不能防止反射攻擊的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM