2012-05-31 39 views
3

我正在閱讀java.util.concurrent包中的代碼,並且我發現類Unsafe(用於實現這些同步器)有趣。我可能永遠不會在任何實際的代碼中使用它,因爲類名本身似乎不鼓勵這樣做,但出於好奇,我對這個類有兩個問題。是否有可能在用戶代碼中使用Java不安全?

1)。這個類的單訪問是這樣的:

public static Unsafe getUnsafe() { 
     Class cc = sun.reflect.Reflection.getCallerClass(2); 
     if (cc.getClassLoader() != null) 
      throw new SecurityException("Unsafe"); 
     return theUnsafe; 
    } 

因此,如果此方法是從用戶代碼調用,它會拋出異常。如何解決這個問題? (可能通過使自己的類加載自舉類加載器?這可能嗎?)

2)。上面的代碼假定將爲由boostrap類加載器加載的類返回null。但是Class#getClassLoader的javadoc說「某些實現可能使用null來表示引導類加載器」,這意味着在這個假設下沒有任何保證。對於那些違反這個假設的實現,不會不安全的(以及依賴於它的ReentrantLock等各種類)根本無法工作?

謝謝!

回答

4

如何解決此問題?

您可以訪問到類像這樣(提供安全管理器將允許可訪問性的變化):

public static Unsafe getUnsafe() { 
    try { 
      Field f = Unsafe.class.getDeclaredField("theUnsafe"); 
      f.setAccessible(true); 
      return (Unsafe)f.get(null); 
    } catch (Exception e) { /* ... */ } 
} 

對於做違反這一假設的實現,豈不是不安全的。 ..根本無法工作?

Unsafe類的細節也是實現特定的。沒有理由期望這個特定的Unsafe能夠與類加載器子系統的任何其他實現一起工作。

+0

謝謝。我沒有意識到我可以使用反射。 – weidi

0

另一種方式去是使用JVM選項-Xbootclasspath/A: < 目錄和zip/jar文件相隔;>

您可以創建一個簡單的類,它會調用Unsafe.getUnsafe()並追加它引導類路徑。

public class UnsafeAccessor { 

    public static Unsafe getUnsafe() { 
     return Unsafe.getUnsafe(); 
    } 

} 

命令行:

java -Xbootclasspath/a:&lt;path_to&gt;/unsafeaccessor.jar -cp 

以這樣的方式,你會直接添加該類系統引導類加載器。 JVM會將該類視爲JDK的一部分,您可以在代碼中調用UnsafeAccessor.getUnsafe()而不是Unsafe.getUnsafe():

Unsafe unsafe = UnsafeAccessor.getUnsafe(); 
相關問題