天天看點

如何防止單例模式被JAVA反射攻擊

    單例模式相信大家都知道,用過的人不在少數。之前寫過一篇博文《singleton模式四種線程安全的實作》(參見:http://blog.csdn.net/u013256816/article/details/50427061),講訴了單例模式的四種寫法,并指出占位符模式的寫法比較ok,詳見如下:

    但這都是基于一個條件:確定不會通過反射機制調用私有的構造器。

    這裡舉個例子,通過JAVA的反射機制來“攻擊”單例模式:

   運作結果:false

   可以看到,通過反射擷取構造函數,然後調用setAccessible(true)就可以調用私有的構造函數,所有e1和e2是兩個不同的對象。

   如果要抵禦這種攻擊,可以修改構造器,讓它在被要求建立第二個執行個體的時候抛出異常。

   經修改後:

    測試代碼:

    運作結果:

    可以看到,成功的阻止了單例模式被破壞。

    從JDK1.5開始,實作Singleton還有新的寫法,隻需編寫一個包含單個元素的枚舉類型。推薦寫法:

    由此可見這種寫法也可以防止單例模式被“攻擊”。

    而且這種寫法也可以防止序列化破壞單例模式,具體不在舉例了,有關序列化以及單例模式被序列化破壞可以參考博文《JAVA序列化》(連結:http://blog.csdn.net/u013256816/article/details/50474678)。

    單元素的枚舉類型已經成為實作Singleton模式的最佳方法。