Java 9, compatability issue with ClassLoader.getSystemClassLoader

后端 未结 8 1270
面向向阳花
面向向阳花 2020-11-29 09:19

The following code adds jar file to the build path, it works fine with Java 8. However, it throws exception with Java 9, the exception is related to the cast to URLClassLoad

相关标签:
8条回答
  • 2020-11-29 10:14

    Referring to Edi's Solution this worked for me:

    public final class IndependentClassLoader extends URLClassLoader {
    
        private static final ClassLoader INSTANCE = new IndependentClassLoader();
    
        /**
         * @return instance
         */
        public static ClassLoader getInstance() {
    
            return INSTANCE;
        }
    
        private IndependentClassLoader() {
    
            super(getAppClassLoaderUrls(), null);
        }
    
        private static URL[] getAppClassLoaderUrls() {
    
            return getURLs(IndependentClassLoader.class.getClassLoader());
        }
    
        private static URL[] getURLs(ClassLoader classLoader) {
    
            Class<?> clazz = classLoader.getClass();
    
            try {
                Field field = null;
                field = clazz.getDeclaredField("ucp");
                field.setAccessible(true);
    
                Object urlClassPath = field.get(classLoader);
    
                Method method = urlClassPath.getClass().getDeclaredMethod("getURLs", new Class[] {});
                method.setAccessible(true);
                URL[] urls = (URL[]) method.invoke(urlClassPath, new Object[] {});
    
                return urls;
    
            } catch (Exception e) {
                throw new NestableRuntimeException(e);
            }
    
        }
    }
    

    Running within Eclipse, you need to set VM Arguments to JUnit Launch/Debug Configuration. Running with maven via command line you have two options:

    Option 1
    Add following lines to pom.xml :

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.16</version>
                    <configuration>
                        <argLine>--add-opens java.base/jdk.internal.loader=ALL-UNNAMED</argLine>
                    </configuration>
                </plugin>
    

    Option 2

    run mvn test -DargLine="-Dsystem.test.property=--add-opens java.base/jdk.internal.loader=ALL-UNNAMED"

    0 讨论(0)
  • 2020-11-29 10:14

    There's also this guys article that helped me. I could not find the article but... here: https://github.com/CGJennings/jar-loader

    Here's a part of guide inside there there's a jar at release you could read his guide & setup it up.

    I just tried it myself download the jar file which include the class file

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.lang.instrument.Instrumentation;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.jar.JarFile;
    
    public final class classname{
    
        public static void premain(String agentArgs, Instrumentation instrumentation) {
            loadedViaPreMain = true;
            agentmain(agentArgs,instrumentation);
        }
    
        public final static void addToClassPath(File jarfile)throws IOException{inst.appendToSystemClassLoaderSearch(new JarFile(jarfile));}
        public final static void agentmain(String agentArgs, Instrumentation instrumentation) {
          if (instrumentation == null){throw new NullPointerException("instrumentation");}
          if (inst == null) {inst = instrumentation;}
        }
        private static Instrumentation inst;
        private static boolean loadedViaPreMain = false;
    }
    

    I just try it out myself package these code as a package then start the application class with -javaagent:plugin......jar option then call this function.It doesn't change my classpath.I am probably missing some details here.

    Hope you can make it work though.

    0 讨论(0)
提交回复
热议问题