我正在读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)都不会起作用吗?
谢谢!
答案 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();