Я только что прочитал некоторый исходный код из org.apache.cxf.common.logging.JDKBugHacks, а также из http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java., чтобы сделать мой вопрос не слишком широким.:) Я просто прошу один кусок кода в них.
// 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
}
Но я не понял этот комментарий.«Вызов getPolicy сохраняет статическую ссылку на загрузчик класса контекста».И они пытаются использовать JDKBugHacks, чтобы обойти это.
ОБНОВЛЕНИЕ
Я пропустил часть статического блока.Вот.Это ключ.На самом деле это уже имеет кеширование политики.Так зачем же кешировать contextClassLoader?В комментарии он утверждает, что @ объявлен как версия JDK 1.4 - Заменен java.security.Policy.
Я дважды проверил код java / security / Policy.java.Это действительно удалило кэшированный загрузчик классов.Так что мои сомнения верны!:)
@Deprecated
public abstract class Policy {
private static Policy policy;
private static ClassLoader contextClassLoader;
static {
contextClassLoader = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
};
Я также добавляю исходный код getPolicy.
public static Policy getPolicy() {
java.lang.SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkPermission(new AuthPermission("getPolicy"));
return getPolicyNoCheck();
}
static Policy getPolicyNoCheck() {
if (policy == null) {
synchronized(Policy.class) {
if (policy == null) {
String policy_class = null;
policy_class = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<String>() {
public String run() {
return java.security.Security.getProperty
("auth.policy.provider");
}
});
if (policy_class == null) {
policy_class = "com.sun.security.auth.PolicyFile";
}
try {
final String finalClass = policy_class;
policy = java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<Policy>() {
public Policy run() throws ClassNotFoundException,
InstantiationException,
IllegalAccessException {
return (Policy) Class.forName
(finalClass,
true,
contextClassLoader).newInstance();
}
});
} catch (Exception e) {
throw new SecurityException
(sun.security.util.ResourcesMgr.getString
("unable to instantiate Subject-based policy"));
}
}
}
}
return policy;
}
На самом деле я копаю глубже, я нахожу кое-что интересное.Кто-то недавно сообщил об ошибке в Apache CXF об org.apache.cxf.common.logging.JDKBugHacks для этого фрагмента кода.
Чтобы отключить кэширование URL-адресов, JDKBugHacks запускается:
URL url = new URL("jar:file://dummy.jar!/");
URLConnection uConn = url.openConnection();
uConn.setDefaultUseCaches(false);
При наличии системного свойства java.protocol.handler.pkgs это может привести к взаимным блокировкам между системным загрузчиком классов и обработчиком файлового протокола в определенных ситуациях (например, если файловый протокол URLStreamHandler является сигнальным символом).Кроме того, приведенный выше код на самом деле существует только для установки defaultUseCaches только на false, поэтому фактического открытия соединения можно избежать, чтобы ускорить выполнение.
Так что исправление
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 имеет те же проблемы с политикой, но не устарела.