If I have a static variable that is assigned a value from a class that uses a singleton pattern, does that somehow require that all the classes that could potentially assign a value to that static variable to be loaded?
I am working with code that looks something like this (simplified to protect corporate data):
private static DEVICE_FACTORY;
String factoryType = propertyFile.getDeviceFactoryType();
if(factoryType.equals("REAL"))
DEVICE_FACTORY = RealDeviceFactory.getInstance();
else
DEVICE_FACTORY = SimulatedDeviceFactory.getInstance();
The code for each type of factory is in totally different projects. The production version of the application jar does not contain any of the simulated classes. My problem is that when I try to test my production code I am gettting "NoClassDefFoundError
" caused by "ClassNotFoundException
". I have confirmed that the property is correctly set to "REAL" so I have no idea why the JVM is even attempting to create/load the Simulated classes...
EDIT I will try to create a simplified version that demonstrates the problem tomorrow. The stack trace (edited to protected corporate data) is as follows:
java.lang.NoClassDefFoundError: my/package/SimulatedDeviceFactory
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.getMainMethod(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: my.package.SimulatedDeviceFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could it be that I am using the singleton pattern on each type of device factory therefore, even though I am not going to use the SimulatedDeviceFactory, because I am using a static method call from that class the JVM thinks it needs to load it anyway?
If that is the case I could use reflection and a FQCN to resolve that quickly enough...
If the class is already loaded, it delegates the request to parent ClassLoader to load the class. If the ClassLoader is not finding the class, it invokes the findClass() method to look for the classes in the file system. The following diagram shows how ClassLoader loads class in Java using delegation.
Java classes aren't loaded into memory all at once, but when required by an application. At this point, the Java ClassLoader is called by the JRE and these ClassLoaders load classes into memory dynamically. Not all classes are loaded by a single ClassLoader.
Loading involves obtaining the byte array representing the Java class file. Verification of a Java class file is the process of checking that the class file is structurally well-formed and then inspecting the class file contents to ensure that the code does not attempt to perform operations that are not permitted.
A classloader can only actually load a class once! That means that it can only define it once. It can load it many times, but only the first time it will define it.
See http://www.programcreek.com/2013/01/when-and-how-a-java-class-is-loaded-and-initialized/. Classes are loaded when they are referenced in a class file most of the time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With