3

我正在阅读 java.util.concurrent 包中的代码,我发现 Unsafe 类(用于实现这些同步器)很有趣。我可能永远不会在任何实际代码中使用它,因为类名本身似乎不鼓励这样做,但出于好奇,我对这个类有 2 个问题。

1)。这个类的单例访问器是这样的:

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

所以如果这个方法是从用户代码中调用的,它会抛出一个异常。如何解决这个问题?(可能通过引导类加载器加载我自己的类?这可能吗?)

2)。上面的代码假定getClassLoader将为由 boostrap 类加载器加载的类返回 null。但是 javadocClass#getClassLoader说“某些实现可能使用 null 来表示引导类加载器。”,这意味着不能保证这个假设。对于确实违反此假设的实现,Unsafe(以及依赖它的各种类,例如 ReentrantLock)不会完全无法工作吗?

谢谢!

4

2 回答 2

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也是特定于实现的。没有理由期望这个特殊Unsafe的能够与类加载器子系统的任何其他实现一起使用。

于 2012-05-31T07:41:15.690 回答
0

另一种方法是使用 jvm 选项-Xbootclasspath/a: <目录和 zip/jar 文件由;>分隔

您可以创建一个简单的类,该类将调用Unsafe.getUnsafe()并将其附加到 bootclasspath。

public class UnsafeAccessor {

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

}

命令行:

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

通过这种方式,您将直接将此类添加到 System Bootstrap Classloader。JVM 会将类视为 JDK 的一部分,您可以在代码中调用 UnsafeAccessor.getUnsafe() 而不是 Unsafe.getUnsafe():

Unsafe unsafe = UnsafeAccessor.getUnsafe();
于 2012-07-14T14:57:17.987 回答