0

I want to extract static field from another program. That program is launched through java reflection and URLClassLoader:

private static final String ProgramClassName = "com.myproject.MyMainClass"; 
private static final String ProgramLocation = "/home/user/program/22.3.0/launcher/target/program.jar";
private static final String[] ProgramArguments ={""}; 

<...>

URL[] urls = new URL[]{ new URL("jar:file:" + ProgramLocation +"!/")};
URLClassLoader cl = URLClassLoader.newInstance(urls, getClass().getClassLoader());
Class<?> classToLoad = Class.forName (ProgramClassName , true, cl);
Method method = classToLoad.getDeclaredMethod ("main", String[].class);
Object instance = classToLoad.newInstance ();
Object result = method.invoke (instance, (Object)ProgramArguments);

Class com.myProject.MyMainClass uses a static field of another class AnotherMyClass placed in different JAR.

That JAR is loaded properly. I know it because program returns correct result (that is based on AnotherMyClass). But when i try to access AnotherMyClass field i get exception:

Class<?> anotherClass = Class.forName (AnoterhClassName, true, cl);
java.lang.ClassNotFoundException: com.anotherproject.AnotherClass
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
    at java.base/java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:872)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:467)

How could i load exactly that instance of class that was used by method.invoke (instance, (Object)ProgramArguments); call? Or maybe there is another way to launch another program and extract static field as result?

  • Thanks for your observation. Main problem still not solved yet, but I've corrected problem description in this topic. I confused error messages. I've checked the message to be sure and you were right I got error message with dots, that is exactly the same you posted. – Igor Adamovich Jul 07 '23 at 22:06
  • `javac` can inline constant fields at compile time. If `MyMainClass` only uses `static final` fields from `AnotherMyClass`, it may never trigger a load of that class. See https://stackoverflow.com/q/3524150/29470. What makes you think that the JAR containing `AnotherMyClass` should be visible to `cl`? It hasn’t been provided directly in the list of URLs. Should it be visible to the parent classloader? – Tim Moore Jul 08 '23 at 00:22
  • `AnotherMyClass` has only static fields and methods. There are no instances of this class. About visibility i can't say anything. I only know that static class was used during execution of `method.invoke`. And the question may be: how to make that static field visible? – Igor Adamovich Jul 08 '23 at 09:07
  • “I only know that static class was used during execution of method.invoke.” How do you know that? Please be specific about how it’s used. If that class is not in `program.jar` then how do you believe it would be on the classpath? If it’s available to the parent classloader, you should be able to reference it directly, without using reflection. – Tim Moore Jul 08 '23 at 09:33
  • You could also try starting Java with the `-verbose:class` option to verify that `AnotherMyClass` is actually loaded. – Tim Moore Jul 08 '23 at 09:45
  • I started application with ``-verbose:class`` and i can't find any trace of ``com.anotherproject.AnotherClass``. But i placed println with an indicator string in ``AnotherClass.getStaticField()`` method (String like "Got AnotherClass") and i see that string on my screen. This test doesn't access ``AnotherClass`` with reflection because it would get an exception. – Igor Adamovich Jul 08 '23 at 18:41
  • "If it’s available to the parent classloader". I have one main program that launches another child program. And first parent program possibly can access mentioned ``anotherProgram.jar`` file in it's own class path (but currently doesn't). I am launching child program with ``method.invoke``. That child program uses ``anotherProgram.jar`` to store some data in it's static field. I want to transport that data to parent program. Parent program in compile time doesn't know what child program will be launched but it can guarantee that static field in ``anotherProgram.jar`` will be used as storage. – Igor Adamovich Jul 08 '23 at 18:58
  • 1
    You still didn’t explain how “`MyMainClass`” of “`program.jar`” is able to access “`AnotherClass`” of “`anotherProgram.jar`” despite not specified to the `URLClassLoader`. – Holger Jul 10 '23 at 07:27
  • "You still didn’t explain how ``MyMainClass`` of ``program.jar`` is able to access ``AnotherClass``". When ``program.jar`` was compiled and built, ``anotherProgram.jar`` was in the dependency list (as maven artifact) of ``program.jar`` and class ``com.anotherproject.AnotherClass`` was in the import part of ``com.myProject.MyMainClass``. I've made small investigation to acquire answer to your question and now I can defenetly say that ``anotherProgram.jar`` is placed inside of ``program.jar``. One jar file inside main jar arhive. – Igor Adamovich Jul 10 '23 at 08:05

0 Answers0