Parent Last Classloader to solve Java Class path hell?

好久不见. 提交于 2019-12-04 16:54:56

I managed to solve this problem. Modified the code of the ParentLastClassLoader to get an array of all the Jarfile paths which are needed by the feature. So when a class is loaded, all the jarfiles needed by the feature will be searched for the .class files. If a class file cannot be found, it will be delegated to the parent.

    private  class ParentLastClassLoader extends ClassLoader {

    private String[] jarFiles; //Paths to the jar files
    private Hashtable classes = new Hashtable(); //used to cache already defined classes

    public ParentLastClassLoader(ClassLoader parent, String[] paths)
    {
        super(parent);
        this.jarFiles = paths;
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException
    {
        System.out.println("Trying to find");
        throw new ClassNotFoundException();
    }

    @Override
    protected synchronized Class<?> 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;
            }

            for(String jarFile: jarFiles){
                try {
                    JarFile jar = new JarFile(jarFile);
                    JarEntry entry = jar.getJarEntry(className.replace(".","/") + ".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);
                } catch (Exception e) {
                    continue;
                }
            }

            result = (Class) classes.get(className);
            if (result != null) {
                return result;
            }
            else{
                throw new ClassNotFoundException("Not found "+ className);
            }
        }
        catch( ClassNotFoundException e ){

            System.out.println("Delegating to parent : " + className);
            // didn't find it, try the parent
            return super.loadClass(className, resolve);
        }
    }
}

The ParentLastClassLoader is instantiated as follows.

ClassLoader loader = new ParentLastClassLoader(Thread.currentThread().getContextClassLoader(), paths);

Once the ParentLastClassLoader is instantiated, the MainClassOfTheFeature will be loaded and its MainMethod will be invoked.

Ok, you created your own classloader and then loaded a class using it. The question is - how does the thread classloader will know about that? So, you must load the class using some classloader, and then set this classloader as thread context classloader.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!