Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to Make a Classloader evaluate the classpath before initlializing static objects?
    primarykey
    data
    text
    <p>I have an application I am developing that uses both jar libraries and native system libraries. My problem is the default classloader attempts to load static classes long before the main is called. Because the classpath doesn't yet contain the native libraries the static classes require, a java.lang.NoClassDefFoundError is thrown at the first evaluated static reference. </p> <p>Here is what my unreachable library loading method looks like:</p> <pre><code>private static void load_libraries() { try { String osname = getOSName(); if (osname == null) { throw new RuntimeException("The system you are running on is not supported"); } URL u = NativeLibs.class.getResource(osname); URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); Class urlClass = URLClassLoader.class; Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class}); method.setAccessible(true); method.invoke(urlClassLoader, new Object[]{u}); } catch (IllegalAccessException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex); } catch (IllegalArgumentException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex); } catch (InvocationTargetException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex); } catch (NoSuchMethodException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex); } catch (SecurityException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex); } } </code></pre> <p>So, let me explain what is going on here. First all getOSName() does is return a string representing the OS family I am running on. It returns null if the OS is unsupported. Just in case I have a problem in that method, I'll go ahead and post it as well:</p> <pre><code>private static String getOSName() { String os = System.getProperty("os.name").toLowerCase(Locale.US); if (os.indexOf("win") &gt;= 0) { return "windows"; } else if (os.indexOf("mac os x") &gt;= 0) { return "macosx"; } else if (os.indexOf("nux") &gt;= 0) { return "linux"; } else if (os.indexOf("solaris") &gt;= 0) { return "solaris"; } else { return null; } } </code></pre> <p>The strings it returns are directory names that the method load_libraries() uses to define a relative URL that I pass to the classloader reflectively to load the libraries. My problem is that the runtime execution never reaches load_libraries(), even though that is the first method in main. </p> <p>One solution that is obvious is to load native libraries statically with customized jars. I don't want to statically link the native libraries if it is at all avoidable, because that defeats the purpose of java's platform portability. Another solution I have already deduced is a system executable that can run the applications jar with a determined automatic classpath from the system executable, but still, that solution requires multiple excutables that are platform specific.</p> <p>So, here is my question:</p> <p>Can I force the classloader to run my Library loading method before it intializes static objects? Will this require a customized ClassLoader? If it does require a custom ClassLoader, will simply passing the system property representing the default classloader solve the problem?</p> <p>Thanks, I hope I wrote a detailed enough question!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload