Custom URLClassLoader, NoClassDefFoundError when run

前端 未结 3 1760
忘掉有多难
忘掉有多难 2021-01-21 03:03

I\'ve created my own URLClassLoader, and set it as the system classloader via java.system.class.loader. It\'s initialized and everything, but the clas

3条回答
  •  Happy的楠姐
    2021-01-21 03:53

    Since the offending line is not the Class.forName but the actual initialization of an instance of Point, we'll have to make sure that the class, that tries to load the Point class, was created by the Library class loader. Therefore, I made some minor changes in the LibraryLoader accordingt to this blog entry

    public class LibraryLoader extends URLClassLoader {
    
        public LibraryLoader(ClassLoader classLoader) {
            super(new URL[0], classLoader);
        }
    
        synchronized public void addJarToClasspath(String jarName)
                throws MalformedURLException, ClassNotFoundException {
            File filePath = new File(jarName);
            URI uriPath = filePath.toURI();
            URL urlPath = uriPath.toURL();
    
            System.out.println(filePath.exists());
            System.out.println(urlPath.getFile());
    
            addURL(urlPath);
        }
    
        @Override
        public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
            if ("mp.MyProgram".equals(name)) {
                return getClass(name);
            }
            return super.loadClass(name, resolve);
        }
    
        private Class getClass(String name) throws ClassNotFoundException {
            String file = name.replace('.', File.separatorChar) + ".class";
            byte[] b = null;
            try {
                b = loadClassData(file);
                Class c = defineClass(name, b, 0, b.length);
                resolveClass(c);
                return c;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        private byte[] loadClassData(String name) throws IOException {
            InputStream stream = getClass().getClassLoader().getResourceAsStream(
                    name);
            int size = stream.available();
            byte buff[] = new byte[size];
            DataInputStream in = new DataInputStream(stream);
            in.readFully(buff);
            in.close();
            return buff;
        }
    }
    

    In the program itself, we have to extract a new method since all the classes, that are used from within a method, seem to be loaded up-front:

    public class MyProgram {
        public static void main(String[] args) {
            LibraryLoader loader = (LibraryLoader) ClassLoader.getSystemClassLoader();
    
            String architecture = System.getProperty("os.arch");
            try {
                loader.addJarToClasspath("swt.jar");
                otherMethod();
    
            } catch (Throwable exception) {
                // println instead of logger because logging is useless at this level
                exception.printStackTrace();
                System.out.println("Could not load SWT library");
                System.exit(1);
            }
        }
    
        protected static void otherMethod() {
            org.eclipse.swt.graphics.Point pt = new org.eclipse.swt.graphics.Point(0, 0);
            System.out.println("Works!");
        }
    }
    

    That should work for you.

提交回复
热议问题