2010-04-16 51 views
6

假設我在我的應用程序的外部庫中有一個單例類。但我仍然可以使用反射來創建該特定類的實例。像這樣Java反射框架和安全

Class clas = Class.forName(Private.class.getName()); 

    for(Constructor c : clas.getDeclaredConstructors()){ 
     c.setAccessible(true); 
     Private p = (Private) c.newInstance(); 
     System.out.println(p); 
    } 

我該如何限制? 。

由於 Ĵ

+0

啊單身的痛苦.. – 2010-04-16 11:54:23

+2

參見:http://stackoverflow.com/questions/2481862/how-to-limit-setaccessible-to-only-legitimate-uses – polygenelubricants 2010-04-16 11:57:06

回答

6

通過使用SecurityManager和控制步驟,控制ReflectPermission("suppressAccessChecks")example)。

雖然安全管理器會影響性能,但很少在服務器端使用。

+0

[多大性能影響?](http://stackoverflow.com/questions/14903423/security-manager-rarely-used-on-server) – 2013-02-15 21:17:05

0

長話短說:你不能

任何構造函數public,private和private都可以通過反射來訪問,並且可以用來實例化一個新對象。

您需要使用其他方法,例如SecurityManager

0

我不認爲你可以限制這一點。

使用反射訪問其他人的私人部分顯然是一種危險/可疑的做法(snicker),但有時需要使用各種類型的工具和應用程序。

1

如果你談論尤其單身:這是一個原因,最好的方式來實現它們是通過枚舉:

public enum YourSingleton { 
    INSTANCE; 
    // methods go here 
} 

如果你在談論一般使用setAccessible():如果代碼是由你不信任的人寫的,不要做這樣的詭計,你不應該運行它(或運行在沙箱中)。在開發人員中,公共/私人應該被視爲有關如何使用代碼的元信息 - 而不是安全功能。

0

AFAIK這是一種元編程,因此需要檢查不同的抽象層。從Javadoc我想,你應該使用SecurityManager來執行你想要的行爲:setAccessible()。 一般恕我直言,你應該真的知道你在做什麼,當你是元編程和改變訪問應該真的有很好的理由要做。

0

你可以這樣做。

private static final Private INSTANCE = new Private(); 
    private Private() { 
     if(INSTANCE !=null) 
      throw new IllegalStateException("Already instantiated"); 
    } 
    public static Private getInstance() { 
      return INSTANCE; 
     } 
+0

單身人士在第三方罐子的範圍之外。所以這根本無濟於事。這種技術是不安全的,因爲你可以通過反射來改變它(正如問題中提到的那樣)。 – whiskeysierra 2010-04-17 17:27:30