Класс, загруженный с помощью ClassLoader, не имеет доступа к измененным переменным - PullRequest
0 голосов
/ 13 января 2020

У меня проблема: есть класс, скомпилированный из внешнего. 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);

в этом классе есть метод:

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

Вот c метод для вызова загруженного метода:

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

Загруженный метод вызывает другой метод:

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

У меня есть еще два класса для взаимодействия:

// 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);
    }
  }

Вот пример вызова метода Loaded:

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

Когда я запускаю свое приложение через Eclipse, я получаю:

Ваш НОВЫЙ номер: 10

Ваш число: 10

Но когда я компилирую его в работоспособный .jar, я получаю другой результат:

Ваш НОВЫЙ номер: 10

Ваш число: 5

И вот вопрос: что я делаю не так?

1 Ответ

0 голосов
/ 13 января 2020

Два объекта класса одинаковы, если они имеют одинаковое имя и один и тот же ClassLoader. Вы загрузили два разных класса , каждый из которых назван MyClass1.

MyClass1.Number в вашем Class_Loader отличается от MyClass1.Number, вызванного из MyClass2 в ClassLoader вашей основной программы. Это не одно и то же поле, потому что они не в одном классе.

...