我正在从事的项目是一个支持两个不同平台的API。在运行时,类路径上实际上只有两个平台之一可用。
在大多数情况下,我很容易就能编写出这样工作正常的代码
if (isPlatformOne()) {
PlatformOne.doSomething();
}
Even if PlatformOne
运行时不存在,预先检查意味着代码不会运行并且不会抛出错误。这种技术适用于大多数情况,但是我遇到过一种抛出错误的情况。
If PlatformOne
还实现了一个不存在的接口并且与也不存在的参数一起使用,然后NoClassDefFoundError
加载包含类时立即抛出,无论代码是否实际执行。
这是一个例子:
界面:
public interface DeleteInterface {
void test(DeleteInterface delete);
}
Class:
public class DeleteClass implements DeleteInterface {
@Override
public void test(DeleteInterface delete) {
}
}
Main:
public class Test {
private final boolean test; //Cannot be constant or compiler will erase unreachable code
public Test() {
test = false;
}
public static void main(String[] args) {
if (new Test().test) {
DeleteClass c = new DeleteClass();
c.test(c);
}
System.out.println("SUCCESS!");
}
}
正在删除DeleteClass
and DeleteInterface
从 jar 中生成的运行时会产生以下错误:
A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: com/kmecpp/test/DeleteInterface
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: com.kmecpp.test.DeleteInterface
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
为什么仅针对这种特定情况抛出错误?在不访问任何目标平台代码的情况下解决该问题的最佳方法是什么?