Api 为什么认为Policy.getPolicy()会保留对上下文的静态引用,并可能导致内存泄漏
我刚刚读了一些源代码,它们来自org.apache.cxf.common.logging.jdbughughacks,也在 . 为了让我的问题清楚,不要太宽泛。:) 我只要求他们写一段代码Api 为什么认为Policy.getPolicy()会保留对上下文的静态引用,并可能导致内存泄漏,api,memory-leaks,java,Api,Memory Leaks,Java,我刚刚读了一些源代码,它们来自org.apache.cxf.common.logging.jdbughughacks,也在 . 为了让我的问题清楚,不要太宽泛。:) 我只要求他们写一段代码 // Calling getPolicy retains a static reference to the context // class loader. try { // Policy.getPoli
// Calling getPolicy retains a static reference to the context
// class loader.
try {
// Policy.getPolicy();
Class<?> policyClass = Class
.forName("javax.security.auth.Policy");
Method method = policyClass.getMethod("getPolicy");
method.invoke(null);
} catch (Throwable e) {
// ignore
}
设置java.protocol.handler.pkgs系统属性时,在特定情况下(例如,如果文件协议URLStreamHandler是signleton),可能会导致系统类加载器和文件协议处理程序之间的死锁。
除此之外,上面的代码实际上是为了将defaultUseCaches设置为false only,因此可以避免实际打开连接,从而加快执行速度
所以解决办法是
URL url = new URL("jar:file://dummy.jar!/");
URLConnection uConn = new URLConnection(url) {
@Override
public void connect() throws IOException {
// NOOP
}
};
uConn.setDefaultUseCaches(false);
JDK或apache cxf出现一些小错误是正常的。通常,他们会修复它。
javax.security.auth.login.Configuration与Policy有相同的问题,但没有被弃用。java 6中的Policy类包含对类加载器的静态引用,该类加载器在首次访问该类时初始化为当前线程上下文类加载器:
private static ClassLoader contextClassLoader;
static {
contextClassLoader =
(ClassLoader)java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction() {
public Object run() {
return Thread.currentThread().getContextClassLoader();
}
});
};
Tomcats lifecycle listener确保在上下文类加载器设置为系统类加载器的已知环境中初始化此类。如果该类是首次从webapp中访问的,它将保留对webapp类加载器的引用。这将防止webapps类被垃圾收集,从而造成perm gen空间泄漏。回答得很好,Horstmann!因此,您的答案很清楚,Tomcat人员确保将类加载器设置为系统类加载器。由于如果设置为webapps类加载器,在重新部署时会造成一些问题?另一个问题,为什么Polocy类需要保存类加载器引用?只是因为它需要在静态块中初始化它?似乎不需要缓存类加载器,因为它已经缓存了策略实例。@Clark Bao,正确,它似乎只使用classloader字段来加载静态策略对象。但由于javax.security.auth.Policy已被弃用,我认为这不会得到解决。我不确定我是否理解您关于URLConnection的观点。因为您最初的问题是关于Policy类的,所以我认为最好再问一个关于
defaultUseCaches
的问题。是有意义的。我会考虑提出另一个问题。我的新相关问题在这里。
URL url = new URL("jar:file://dummy.jar!/");
URLConnection uConn = url.openConnection();
uConn.setDefaultUseCaches(false);
URL url = new URL("jar:file://dummy.jar!/");
URLConnection uConn = new URLConnection(url) {
@Override
public void connect() throws IOException {
// NOOP
}
};
uConn.setDefaultUseCaches(false);
private static ClassLoader contextClassLoader;
static {
contextClassLoader =
(ClassLoader)java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction() {
public Object run() {
return Thread.currentThread().getContextClassLoader();
}
});
};