是否可以在用户代码中使用Java Unsafe?

时间:2012-05-31 07:36:29

标签: java classloader

我正在读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。但是Class#getClassLoader的javadoc说“有些实现可能使用null来表示引导类加载器。”,这意味着在这个假设上没有保证。对于违反此假设的实现,不安全(以及依赖于它的各种类,如ReentrantLock)都不会起作用吗?

谢谢!

2 个答案:

答案 0 :(得分: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能够与类加载器子系统的任何其他实现一起使用。

答案 1 :(得分:0)

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

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

public class UnsafeAccessor {

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

}

命令行:

java -Xbootclasspath/a:<path_to>/unsafeaccessor.jar -cp

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

Unsafe unsafe = UnsafeAccessor.getUnsafe();