[英]Failing to load class definition from jar
尝试将应用程序移植到JApplet
时,我遇到了一个问题,因此它可以在浏览器上运行。
课程内容:
CustomClassLoader
实现。 存储在网站上。 问题:
尝试使用CustomClassLoader
在内容目录中加载.class文件时,我得到NoClassDefFoundError
。
这个错误虽然无法实现,但却与jar中的一个类有关。 这门课是抽象的。 内容目录中的所有.class文件都扩展此类并填充所有必需的方法。 加载这些类后,将引发错误。 程序,当正常运行java -jar file.jar
,工作得很好。
这让我相信它与classpath有关。
安全设置:
我通过appletviewer
命令运行applet,如下所示:
appletviewer -J-Djava.security.policy=policy file.html
在同一目录中是我的策略文件:
grant {
permission java.lang.RuntimePermission "getenv.APPDATA";
permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete, execute";
permission java.lang.RuntimePermission "exitVM";
permission java.util.PropertyPermission "user.name", "read";
permission java.lang.RuntimePermission "createClassLoader";
};
据我所知,没有其他安全例外被抛出。 小程序已签名。
用于加载Applet的HTML文件:
<!DOCTYPE html>
<html>
<body>
<object width="1000" height="600" classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4-windows-i586.cab#Version=1,4,0,0">
<param name="archive" value="file.jar"/>
<param name="code" value="package.to.Boot"/>
</object>
</body>
</html>
非常感谢任何帮助解决这个问题。
CustomClassLoader.java:
package org.obicere.cc.methods;
import java.io.File;
public class CustomClassLoader extends ClassLoader {
//...
private Class<?> loadClass(final File file) {
try {
final byte[] data = IOUtils.readData(file);
return super.defineClass(file.getName().substring(0, file.getName().length() - 6), data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
示例Runner:CanReachRunner.java
import java.lang.reflect.Method;
import java.util.Random;
import org.obicere.cc.executor.Result;
import org.obicere.cc.tasks.projects.Runner;
public class CanReachRunner extends Runner {
@Override
public Result[] getResults(Class<?> clazz) {
try {
final Method method = clazz.getMethod("canReach", int.class, int.class, int.class);
final Random ran = new Random();
final Result[] results = new Result[10];
for (int i = 0; i < 10; i++) {
final int small = ran.nextInt(5) + 5;
final int large = ran.nextInt(5);
final int goal = (small + large * 5) + 5 + ran.nextInt(6);
results[i] = new Result(method.invoke(clazz.newInstance(), small, large, goal), (goal <= small + large * 5) && goal % 5 <= small, small, large, goal);
}
return results;
} catch (Exception e) {
return new Result[] {};
}
}
}
类加载器有几个问题。 第一个是loadClass
方法使用String
的参数而不是File
,该字符串是要加载的类的名称。 这是因为要加载的类可能不在文件中,它可能在网络连接上,并且无论如何JVM都不知道如何查找文件。 第二个是覆盖loadClass
是不好的做法,因为如果这样做,它会干扰默认行为,它首先尝试以正常方式加载类,并且只有在不起作用的情况下才会调用findClass
方法。 因此,您应该覆盖findClass
而不是defineClass
。 这是更新的代码:
public class CustomClassLoader extends ClassLoader {
private Class<?> findClass(String class) {
try {
File contentDir = ...; // You have to fill this in with the location of the content dir
final byte[] data = IOUtils.readData(new File(contentDir, class + ".class");
return defineClass(class, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
您必须以某种方式找到内容目录并使用它来初始化contentDir
。
这个作为jar运行时的原因是因为它能够加载类而无需自定义类加载器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.