In Java, what's the proper way of using an optional dependency without ClassNotFoundError
?
The simple way is to use Class.forName
.
I would also like to avoid loading backends using Class.forName
.
Erm ... OK.
Can you help me understand if any of these will lead to a ClassNotFoundError
for unshaded library and which will not?
If I understand what you are proposing correctly, none of them will work.
Leaving an unused class field, of type from this library
Loading the class that defines that field will trigger1 loading the library that defines the type of the field.
Leaving an unused method, with arguments or return from this library
Loading the class that defines that method will trigger1 loading the library that defines the argument or return type.
Referencing this library in a backend class that will only be loaded conditionally like:
backend = isNewBackend ? new FancyBackend() : new OldBackend()
The code that does that calculation needs to be defined in a class. To running that code that is liable to trigger1 loading both the FancyBackend
and OldBackend
classes to verify the code.
If you wanted to avoid explicit Class.forName
calls, you could potentially implement your optional dependency as a custom Service Provider Interface (SPI). That gives you additional flexibility, but it is more complicated than simply using Class.forName
.
Here are some references for SPIs:
1 - Per Does the JVM throw if an unused class is absent? if the JVM implements lazy class loading, loading may not be triggered by mentioning a class in a method or field signature. However, lazy loading is implementation dependent and (AFAIK) not specified. So relying on the JVM to do it will make your application platform dependent.