Search code examples
javamethodsjarclassloaderinvocation

A class loaded with ClassLoader don't have access to changed variables


I have a problem: There is a class compiled from external .java file

    private static Class<?> LoadedClass;
    private static Object LoadedClassInstance;
    public static Method LoadedMethod;

[SKIP]

   private static Path compileSource(Path javaFile) {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        compiler.run(null, null, null, javaFile.toFile().getAbsolutePath());
        return javaFile.getParent().resolve("LoadedClass.class");
    }

    private static void runClass(Path javaClass)
            throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
        URL classUrl = javaClass.getParent().toFile().toURI().toURL();
        URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{classUrl});
        LoadedClass = Class.forName("LoadedClass", true, classLoader);

in this class there is a method:

        LoadedClassInstance = LoadedClass.getDeclaredConstructor().newInstance(); 
        LoadedMethod = LoadedClass.getDeclaredMethod("DoTheMethod");                
    }

Here is a static method to invoke loaded method:

    public static void CallLoadedMethod() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        LoadedMethod.invoke(LoadedClassInstance);   
    }

Loaded method calls the other method:

    import MyApp.MyClass1;
[SKIP]
    public static void DoTheMethod() {
        System.out.println("Your number is : "+MyClass1.Number);    
    }

I have two more classes to interract with:

// MyClass1
    public static int Number = 5;
  public class MyClass1 {
    // DoSomeStuff
  }

// MyClass2
  public class MyClass2 {
    public static void SetTheNumberTo(int number){
        MyClass1.Number = number;
        System.out.println("Your NEW number is : "+MyClass1.Number);
    }
  }

Here is Loaded method invoke example:

    MyClass2.SetTheNumberTo(10);
    Class_Loader.DoTheMethod();

When i run my app through Eclipse i get:

Your NEW number is : 10

Your number is : 10

But when i compile it to runnable .jar i get the other result :

Your NEW number is : 10

Your number is : 5

And here is the question: what am i doing wrong?


Solution

  • Two class objects are the same if they have both the same name and the same ClassLoader. You have loaded two different classes which each are named MyClass1.

    MyClass1.Number in your Class_Loader is different from MyClass1.Number invoked from MyClass2 in your main program’s ClassLoader. They are not the same field because they are not in the same class.