如果我有一个静态变量,该变量是从使用单例模式的类中赋值的,那么这是否会要求所有可能为该静态变量赋值的类加载?
我正在使用看起来像这样的代码(简化以保护公司数据):
private static DEVICE_FACTORY;
String factoryType = propertyFile.getDeviceFactoryType();
if(factoryType.equals("REAL"))
DEVICE_FACTORY = RealDeviceFactory.getInstance();
else
DEVICE_FACTORY = SimulatedDeviceFactory.getInstance();
每种工厂的代码都是完全不同的项目。应用程序jar的生产版本不包含任何模拟类。我的问题是,当我尝试测试我的生产代码时,我得到了由“NoClassDefFoundError
”引起的“ClassNotFoundException
”。我已确认该属性已正确设置为“REAL”,因此我不知道为什么JVM甚至试图创建/加载模拟类...
编辑我将尝试创建一个明天演示问题的简化版本。堆栈跟踪(编辑为受保护的公司数据)如下:
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)
可能是因为我在每种类型的设备工厂上使用单例模式,即使我不打算使用SimulatedDeviceFactory,因为我使用来自该类的静态方法调用,JVM认为它需要加载无论如何呢?
如果是这种情况,我可以使用反射和FQCN来快速解决这个问题......
答案 0 :(得分:1)
见http://www.programcreek.com/2013/01/when-and-how-a-java-class-is-loaded-and-initialized/。 在大多数情况下在类文件中引用类时会加载类。
答案 1 :(得分:0)
这就是Java的工作原理。在加载主类时加载SimulatedDeviceFactory。
在这种情况下你应该使用反射。这是很好的,很常见的模式。易于配置且易于调试。
避免使用任何其他解决方法。在JEE应用程序服务器中解决类加载器相关问题真的很痛苦。