gpt4 book ai didi

java - 使用反射和 ClassLoaders 创建类的实例时出现 ClassCastException

转载 作者:搜寻专家 更新时间:2023-10-31 20:16:09 25 4
gpt4 key购买 nike

首先,这是Java 1.4(项目限制)。我正在尝试创建一个应用程序管理器。它使用自己的自定义类加载器实例加载每个应用程序的主类。之后,它使用反射创建主类的实例。每个应用程序都实现一个公共(public)接口(interface),因此在创建实例后,它会运行应用程序的预定义方法。

但是,我在 CRASH POINT 1 遇到了一些麻烦(见代码)。该类未被识别为其接口(interface)的一种实现。如果我注释这个代码块,我会在崩溃点 2 处得到 ClassCastException。

我想这两个错误都与同一个问题有关(当然)。

谁能帮帮我?代码的相关部分如下(导入已删除)...

非常感谢。

马库斯

//AppManager.java

public class AppManager {
public ThreadGroup threadGroup;
private Class appClass;
private AppInstance appInst;
public AppContextImpl context;

private AppManager(CustomClassLoader cl, String mainClass) throws ClassNotFoundException {
final String className = mainClass;
final CustomClassLoader finalLoader = cl;

appClass = cl.loadClass(mainClass);

// DEBUG CODE:
Class[] k1 = AppInstance.class.getInterfaces();
System.out.println(k1.length + " interfaces for AppInstance.class:");
for (int ii = 0; ii < k1.length; ii++) {
System.out.println(" " + ii + " - " + k1[ii].getName() + " (" + k1[ii].getClassLoader() + ")");
}

Class[] k2 = appClass.getInterfaces();
System.out.println(k2.length + " interfaces for appClass instance:");
for (int ii = 0; ii < k2.length; ii++) {
System.out.println(" " + ii + " - " + k2[ii].getName() + " (" + k2[ii].getClassLoader() + ")");
}

// CRASH POINT 1
if (!(AppInstance.class.isAssignableFrom(appClass))) {
throw new IllegalArgumentException("Attempt to run a non-AppInstance class: " + appClass);
}

context = new AppContextImpl(mainClass, this);
cl.setAppManager(this);
Constructor m;
try {
m = appClass.getConstructor(new Class[0]);
// CRASH POINT 2
appInst = (AppInstance) m.newInstance(new Object[0]);
appInst.init(context);
} catch (Exception e) {
System.out.println("Got ClassCastException here!\n");
e.printStackTrace();
}
}

public static void main(String[] args) {
App app1;

String path1 = "/home/user/workspace/MultiTaskTest/bin/";
String app1Name = "App1";

Vector v1 = new Vector();
try {
v1.add(new URL(path1));
} catch (MalformedURLException e1) {
final File file1 = new File(path1);
try {
URL path1aux = (URL) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws IOException {
if (!file1.exists()) {
System.out.println("Warning: \"" + file1.getPath() + "\" not found");
return null;
}
return file1.toURI().toURL();
}
});

if (path1aux != null) {
v1.add(path1aux);
}
} catch (PrivilegedActionException e) {
e.getException().printStackTrace();
}
}

final URL[] array1 = (URL[]) v1.toArray(new URL[v1.size()]);
CustomClassLoader cl1 = (CustomClassLoader) AccessController.doPrivileged(
new PrivilegedAction() { public Object run() {
return new CustomClassLoader(array1);
}});
System.out.println("ClassLoader 1 created: " + cl1);
try {
app1 = new App(cl1, app1Name);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("Cannot find class App1.");
}
}
}

//应用实例.java

public interface AppInstance {
public void init(ContextImpl context);
}

//App1.java

public class App1 implements AppInstance {
private AppContextImpl contextObj;

public void init(AppContextImpl context) {
this.contextObj = context;
System.out.println("Running App1...");
}
}

//AppContextImpl.java

public class AppContextImpl {
public String mainClass;
public AppManager app;

public AppContextImpl(String mainClass, AppManager app) {
this.mainClass = mainClass;
this.app = app;
}
}

//自定义类加载器.java

public class CustomClassLoader extends URLClassLoader {
AppManager appInst;

public CustomClassLoader(URL[] paths) { super(paths, null); }
public void setAppManager(AppManager app) { this.appInst = app; }
}

AppManager.java 文件中调试代码的输出是:

0 interfaces for AppInstance.class:
1 interfaces for appClass instance:
0 - AppInstance (CustomClassLoader@480457)

最佳答案

您的 AppInstance 类可能由每个自定义类加载器单独加载。由于类对象依赖于实际的类和类加载器,它们实际上是不同的类。所以来自类加载器 1 的 AppInstance 与来自类加载器 2 的 AppInstance 不同。

您需要做的是使用标准的类加载器层次结构:为您的应用程序使用根类加载器,并确保 AppInstance 可由类加载器加载。然后让你的自定义类加载器从根开始。每当他们需要访问 AppInstance 类时,他们将使用从根加载的内容。

所以,而不是这个:

public CustomClassLoader(URL[] paths) { super(paths, null); }

您需要为您的 CustomClassLoader 提供父级

关于java - 使用反射和 ClassLoaders 创建类的实例时出现 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2999824/

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