这个可以避免加载缓存
import java.io.IOException; import java.lang.ref.SoftReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.JarURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.jar.JarFile; /** * A utility class for working around the java webstart jar signing/security bug * * see http://bugs.sun.com/view_bug.do?bug_id=6967414 and http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6805618 * @author Scott Chann */ public class JarSignersHardLinker { // private static final Logger LOG = LoggerFactory.getLogger(JarSignersHardLinker.class); private static final String JRE_1_6_0 = "1.6.0_"; private static final String JRE_1_7 = "1.7"; /** * the 1.6.0 update where this problem first occurredd */ private static final int PROBLEM_JRE_UPDATE = 19; public static final List sm_hardRefs = new ArrayList(); protected static void makeHardSignersRef(JarFile jar) throws java.io.IOException { //System.out.println("Making hard refs for: " + jar); if (jar != null && jar.getClass().getName().equals("com.sun.deploy.cache.CachedJarFile")) { //lets attempt to get at the each of the soft links. //first neet to call the relevant no-arg method to ensure that the soft ref is populated //then we access the private member, resolve the softlink and throw it in a static list. callNoArgMethod("getSigners", jar); makeHardLink("signersRef", jar); callNoArgMethod("getSignerMap", jar); makeHardLink("signerMapRef", jar); // callNoArgMethod("getCodeSources", jar); // makeHardLink("codeSourcesRef", jar); callNoArgMethod("getCodeSourceCache", jar); makeHardLink("codeSourceCacheRef", jar); } } /** * if the specified field for the given instance is a Soft Reference * That soft reference is resolved and the returned ref is stored in a static list, * making it a hard link that should never be garbage collected * @param fieldName * @param instance */ private static void makeHardLink(String fieldName, Object instance) { // System.out.println("attempting hard ref to " + instance.getClass().getName() + "." + fieldName); try { Field signersRef = instance.getClass().getDeclaredField(fieldName); signersRef.setAccessible(true); Object o = signersRef.get(instance); if (o instanceof SoftReference) { SoftReference r = (SoftReference) o; Object o2 = r.get(); sm_hardRefs.add(o2); } else { // System.out.println("noooo!"); } } catch (NoSuchFieldException e) { e.printStackTrace(); return; } catch (IllegalAccessException e) { e.printStackTrace(); } } /** * Call the given no-arg method on the given instance * @param methodName * @param instance */ private static void callNoArgMethod(String methodName, Object instance) { // System.out.println("calling noarg method hard ref to " + instance.getClass().getName() + "." + methodName + "()"); try { Method m = instance.getClass().getDeclaredMethod(methodName); m.setAccessible(true); m.invoke(instance); } catch (SecurityException e1) { e1.printStackTrace(); } catch (NoSuchMethodException e1) { e1.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } /** * is the preloader enabled. ie: will the preloader run in the current environment * @return */ public static boolean isHardLinkerEnabled() { return isRunningOnJre1_6_0_19OrHigher() && isRunningOnWebstart(); } /** * is the application currently running on webstart * * detect the presence of a JNLPclassloader * * @return */ public static boolean isRunningOnWebstart() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); while (cl != null) { if (cl.getClass().getName().equals("com.sun.jnlp.JNLPClassLoader")) { return true; } cl = cl.getParent(); } return false; } /** * Is the JRE 1.6.0_19 or higher? * @return */ public static boolean isRunningOnJre1_6_0_19OrHigher() { String javaVersion = System.getProperty("java.version"); if (javaVersion.startsWith(JRE_1_6_0)) { //then lets figure out what update we are on String updateStr = javaVersion.substring(JRE_1_6_0.length()); try { return Integer.parseInt(updateStr) >= PROBLEM_JRE_UPDATE; } catch (NumberFormatException e) { //then unable to determine updatedate level return false; } } else if (javaVersion.startsWith(JRE_1_7)) { return true; } //all other cases return false; } /** * get all the JarFile objects for all of the jars in the classpath * @return */ public static Set<JarFile> getAllJarsFilesInClassPath() { Set<JarFile> jars = new LinkedHashSet<JarFile>(); for (URL url : getAllJarUrls()) { try { jars.add(getJarFile(url)); } catch (IOException e) { System.out.println("unable to retrieve jar at URL: " + url); } } return jars; } /** * Returns set of URLS for the jars in the classpath. * URLS will have the protocol of jar eg: jar:http://HOST/PATH/JARNAME.jar!/META-INF/MANIFEST.MF */ static Set<URL> getAllJarUrls() { try { Set<URL> urls = new LinkedHashSet<URL>(); Enumeration<URL> mfUrls = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF"); while (mfUrls.hasMoreElements()) { URL jarUrl = mfUrls.nextElement(); // System.out.println(jarUrl); if (!jarUrl.getProtocol().equals("jar")) continue; urls.add(jarUrl); } return urls; } catch (IOException e) { throw new RuntimeException(e); } } /** * get the jarFile object for the given url * @param jarUrl * @return * @throws IOException */ public static JarFile getJarFile(URL jarUrl) throws IOException { URLConnection urlConnnection = jarUrl.openConnection(); if (urlConnnection instanceof JarURLConnection) { // Using a JarURLConnection will load the JAR from the cache when using Webstart 1.6 // In Webstart 1.5, the URL will point to the cached JAR on the local filesystem JarURLConnection jcon = (JarURLConnection) urlConnnection; return jcon.getJarFile(); } else { throw new AssertionError("Expected JarURLConnection"); } } /** * Spawn a new thread to run through each jar in the classpath and create a hardlink * to the jars softly referenced signers information. */ public static void go() { if (!isHardLinkerEnabled()) { System.out.println("Skipping Resource Preloader Hardlinker"); return; } System.out.println("Starting Resource Preloader Hardlinker"); Thread t = new Thread(new Runnable() { public void run() { try { Set<JarFile> jars = getAllJarsFilesInClassPath(); for (JarFile jar : jars) { makeHardSignersRef(jar); } } catch (Exception e) { e.printStackTrace(); //System.out.println("Problem preloading resources: " + e.g); } catch (Error e) { //System.out.println("Error preloading resources: " + ThrowableUtil$.MODULE$.fullStackTrace(e)); e.printStackTrace(); } } }); t.start(); } }