2023-01-20 260
我正在进行的项目是支持两个不同平台的API.在运行时,实际上只有两个平台中的一个将在ClassPath上可用.
在大多数情况下,我很容易编写这样的代码
if (isPlatformOne()) {
PlatformOne.doSomething();
}
即使在运行时不存在PlatformOne,该检查事先意味着代码未运行,也不会丢弃错误.该技术适用于绝大多数情况,但是有一种情况我已经遇到了错误的地方.
如果PlatformOne也实现了不存在的接口,并且与也不存在的参数一起使用,那么当加载包含类时,无论代码是否实际执行,NoClassDefFoundError都会立即抛弃.
这是一个示例:
接口:
public interface DeleteInterface {
void test(DeleteInterface delete);
}
类:
public class DeleteClass implements DeleteInterface {
@Override
public void test(DeleteInterface delete) {
}
}
主:
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和DeleteInterface从罐子中产生以下错误:
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
为什么仅针对这种特定情况会出现错误,而在不访问任何目标平台的代码的情况下,最佳的工作方式是什么?
Java验证器可能会因为必须存在其他验证,例如必须存在其他验证,例如必须存在NoClassDefFoundError,还必须在启动时通过JRE扫描的主类,此外还可以做到这一点.请参阅堆栈跟踪.
移动需要不存在代码的代码到其他类,然后在您要使用它的位置,请先检查该类是否存在,然后从该额外类中调用方法:
class MyExtraClass {
public static void doStuff() {
DeleteClass c = new DeleteClass();
c.test(c);
}
}
public boolean checkForClass(String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
// somewhere in your code
if (checkForClass("package.DeletedClass")) {
MyExtraClass.doStuff();
}
这只是此类情况的最安全选项,同样,如果这是非常短的代码,您可以使用一些本地类:(但在大多数情况下看起来并不好)
)
// somewhere in your code
if (checkForClass("package.DeletedClass")) {
new Runnable() {
@Override
public void run() {
DeleteClass c = new DeleteClass();
c.test(c);
}
}.run();
}
我今天实际上遇到了这个问题.
确保您没有在系统类加载程序中两次加载同一类.
i.
我将代理引用中的名称更改为与前端引用不同,并且错误停止.
删除deleteclass和deleteinterface从jar产生
运行时的以下错误:
如果运行时不存在所需的类,则肯定会被抛弃.
即使PlatformOne在运行时不存在,也要事先进行检查
表示代码不运行,也不会丢弃错误.
请检查您的代码是否消除了错误的错误,如果是,您的应用不会崩溃并可以按正常执行.例如.下面的代码片段将抛出NoClassDefFoundError,但不会崩溃,因为您会消化错误.
public bool isPlatformOne() {
try {
...
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
如果您的用例仅是为了检查特定类是否存在,则可以使用Class.forName检查课程的存在.例如.
// className is the fully qualified class name.
public boolean hasClass(String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
在代码中使用它的示例.
if (hasClass("android.support.v7.app.AppCompatActivity")) {
...
}
以上所述是小编给大家介绍的如何避免Java中未使用的代码抛出的NoclassDeffoundError,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/26011.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态