Note that there are some explanatory texts on larger screens.

plurals
  1. POParent Last Classloader to solve Java Class path hell?
    primarykey
    data
    text
    <p>I have a project which uses two versions of bouncyCastle jars bcprov-jdk15 and bcprov-jdk16. The jvm loads the older version but there is a feature I wrote which needs the newer version to run. I tried to solve this classpath hell by using a custom class loader. After some googling and with the help of some previous Stackoverflow answers<a href="https://stackoverflow.com/questions/13315358/custom-java-classloader-not-being-used-to-load-dependencies">[1]</a> <a href="https://stackoverflow.com/questions/5445511/how-do-i-create-a-parent-last-child-first-classloader-in-java-or-how-to-overr">[2]</a> and this <a href="http://kalanir.blogspot.com/2010/01/how-to-write-custom-class-loader-to.html" rel="nofollow noreferrer">blog</a>, I wrote the following <strong>Parent Last Class loader</strong> to load the classes from the newer jar before delegating to the parent class loader. </p> <pre><code>public class ParentLastClassLoader extends ClassLoader { private String jarFile; //Path to the jar file private Hashtable classes = new Hashtable(); //used to cache already defined classes public ParentLastClassLoader(ClassLoader parent, String path) { super(parent); this.jarFile = path; } @Override public Class&lt;?&gt; findClass(String name) throws ClassNotFoundException { System.out.println("Trying to find"); throw new ClassNotFoundException(); } @Override protected synchronized Class&lt;?&gt; loadClass(String className, boolean resolve) throws ClassNotFoundException { System.out.println("Trying to load"); try { System.out.println("Loading class in Child : " + className); byte classByte[]; Class result = null; //checks in cached classes result = (Class) classes.get(className); if (result != null) { return result; } try { JarFile jar = new JarFile(jarFile); JarEntry entry = jar.getJarEntry(className + ".class"); InputStream is = jar.getInputStream(entry); ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); int nextValue = is.read(); while (-1 != nextValue) { byteStream.write(nextValue); nextValue = is.read(); } classByte = byteStream.toByteArray(); result = defineClass(className, classByte, 0, classByte.length, null); classes.put(className, result); return result; } catch (Exception e) { throw new ClassNotFoundException(className + "Not found", e); } } catch( ClassNotFoundException e ){ System.out.println("Delegating to parent : " + className); // didn't find it, try the parent return super.loadClass(className, resolve); } } } </code></pre> <p>I loaded the main class in the feature with this class loader but the BouncyCaslte classes used in the feature are not loaded by my custom classloader. </p> <pre><code>ClassLoader loader = new ParentLastClassLoader(Thread.currentThread().getContextClassLoader(), pathToJar); Class myClass = loader.loadClass("MainClassOfTheFeature"); Method mainMethod = myClass.getMethod("MainMethod"); mainMethod.invoke(myClass.getConstructor().newInstance()); </code></pre> <p>Jvm still uses the classes it loaded from the older version. How can I make the JVM to load the classes from my class loader when running the feature and use the already loaded older classes in the older jar when the feature is not running?</p> <p><strong>Edit:</strong> The problem remains even after setting the custom classloader as the Thread context classloader in the MainMethod of the feature Main class.</p> <pre><code>Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); </code></pre>
    singulars
    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.
 

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