testing for a class having been loaded

Peter Levart peter.levart at gmail.com
Wed Nov 30 17:52:10 UTC 2016


Hi Alan,

On 11/29/2016 10:14 PM, Alan Snyder wrote:
> Prior to JDK 9, it was possible (using setAccessible) to ask a ClassLoader whether a class with a given name had been loaded without actually forcing it to be loaded.
>
> This hack will not work in JDK9, so I am wondering if there is a way to do this?
>
> If not, can someone explain why it would be a bad thing to be able to do this?
>
> Here is my use case:
>
> I have two classes, A and B, that have been designed to be aware of each other, but are packaged in separate JAR files or modules that can be loaded independently. My goal is for these classes to make a runtime connection with each other, but only if both have been loaded by the application.
>
> If each class can at load (initialization) time test whether the other has been loaded, then they can use reflection to make that connection.
>
> All of the other solutions I have thought of require yet a third class/interface C that is separately packaged and loaded by both A and B. This is feasible, but seems unnecessary.

Why separately packaged? You could do something like the following:


package pkga;

public class ClassA {

     public static final class Loaded {
         private static boolean loaded;
         public static boolean isLoaded() { return loaded; }
     }

     static {
         try {
             Class<?> bLoadedClass = Class.forName("pkgb.ClassB$Loaded");
ClassA.class.getModule().addReads(bLoadedClass.getModule());
             java.lang.reflect.Method bLoadedMethod = 
bLoadedClass.getMethod("isLoaded");
             synchronized (ClassA.Loaded.class) {
                 ClassA.Loaded.loaded = true;
                 boolean bLoaded = (Boolean) bLoadedMethod.invoke(null);
                 if (bLoaded) {
                     connect();
                 }
             }
         } catch (ReflectiveOperationException ignore) {
             // ClassB.Loaded not visible
         }
     }

     private static void connect() {
         System.out.println("Connecting from A -> B");
     }

     public static void use() {
         System.out.println("A used.");
     }
}


package pkgb;

public class ClassB {

     public static final class Loaded {
         private static boolean loaded;
         public static boolean isLoaded() { return loaded; }
     }

     static {
         try {
             Class<?> aLoadedClass = Class.forName("pkga.ClassA$Loaded");
ClassB.class.getModule().addReads(aLoadedClass.getModule());
             java.lang.reflect.Method aLoadedMethod = 
aLoadedClass.getMethod("isLoaded");
             synchronized (aLoadedClass) {
                 ClassB.Loaded.loaded = true;
                 boolean aLoaded = (Boolean) aLoadedMethod.invoke(null);
                 if (aLoaded) {
                     connect();
                 }
             }
         } catch (ReflectiveOperationException ignore) {
             // ClassA.Loaded not visible
         }
     }

     private static void connect() {
         System.out.println("Connecting from B -> A");
     }

     public static void use() {
         System.out.println("B used.");
     }
}




Regards, Peter



More information about the jigsaw-dev mailing list