gpt4 book ai didi

java - 无法从 jar 加载类定义

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:21:50 25 4
gpt4 key购买 nike

我在尝试将应用程序移植到 JApplet 以便它可以在浏览器上运行时遇到了一个问题。

计划内容:

  1. Jar 文件。包含我的 CustomClassLoader 实现。存储在网站上。
  2. 内容目录。充满编译类。存储在用户计算机上。

问题:

当我尝试使用我的 CustomClassLoader 加载内容目录中的 .class 文件时,我收到了一个 NoClassDefFoundError

该错误虽然无法实现,但与 jar 中的一个类有关。类是抽象的。内容目录中的所有 .class 文件都扩展了此类并填充了所有必需的方法。加载这些类时,会抛出错误。该程序在 java -jar file.jar 正常运行时运行良好。

这让我相信它与类路径有关。

安全设置:

我正在通过 appletviewer 命令运行小程序,如下所示:

 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";
};

据我所知,没有抛出其他安全异常。小程序已签名。

用于加载小程序的 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;
}
}

运行器示例: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 运行时起作用的原因是它能够在不需要自定义类加载器的情况下加载类。

关于java - 无法从 jar 加载类定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17944506/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com