testing for a class having been loaded
Peter Levart
peter.levart at gmail.com
Wed Nov 30 18:23:50 UTC 2016
On 11/30/2016 07:07 PM, Alan Snyder wrote:
> Why separately packaged? The goal would be loose coupling allowing
> smaller images. Same goal as Jigsaw…
>
> Your solution uses Class.forName(), which will load classes. Perhaps
> it works, but doesn’t it rely on implementation specific behavior for
> nested static classes?
>
> Alan
You can create a top-level class if you are worried. You don't even need
two "Loaded" classes. One "Rendezvous" class is enough. Like this:
package pkga;
public final class Rendezvous {
private static Class<?> aClass, bClass;
static synchronized void aLoaded(Class<?> aCl) {
aClass = aCl;
if (bClass != null) {
connect();
}
}
public static synchronized void bLoaded(Class<?> bCl) {
bClass = bCl;
if (aClass != null) {
connect();
}
}
private static void connect() {
System.out.println("Connecting " + aClass + " with " + bClass);
}
}
package pkga;
public class A {
static {
Rendezvous.aLoaded(A.class);
}
public static void use() {
System.out.println("A used.");
}
}
package pkgb;
public class B {
static {
try {
Class<?> rendezvousClass = Class.forName("pkga.Rendezvous");
B.class.getModule().addReads(rendezvousClass.getModule());
rendezvousClass.getMethod("bLoaded",
Class.class).invoke(null, B.class);
} catch (ReflectiveOperationException ignore) {
// A$Rendezvous not visible
}
}
public static void use() {
System.out.println("B used.");
}
}
Regards, Peter
>
>
>
>> On Nov 30, 2016, at 9:52 AM, Peter Levart <peter.levart at gmail.com
>> <mailto:peter.levart at gmail.com>> wrote:
>>
>> 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