在类加载器中投掷?
我该如何做到这一点:
class Foo { public static Foo get() throws Exception { ClassLoader cl = new URLClassLoader(new URL[]{"foo.jar"}, null); // Foo.class is in foo.jar return (Foo)cl.loadClass("Foo").newInstance(); // fails on class cast } }
我需要的是JVM从cl中考虑Foo实例,就好像它是执行代码的类加载器中的Foo实例。
我已经看到了这些方法,没有一个适合我(上面的例子是一个玩具的例子):
- 通过作为调用代码和创build的类加载器的父类的类加载器加载类(或单独的接口)
- 序列化和反序列化对象。
不可能。 类标识由完全限定的名称和类加载器组成。
将一个对象转换成不同类加载器加载的同名类与将String
为Integer
没有区别,因为尽pipe名称相同,但这些类实际上可能完全不同。
我刚刚花了最后两天挣扎在这个确切的问题,我终于通过使用Javareflection来解决问题:
// 'source' is from another classloader final Object source = events[0].getSource(); if (source.getClass().getName().equals("org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptThread")) { // I cannot cast to 'org.eclipse.wst.jsdt.debug.internal.core.model.JavaScriptThread' // so I invoke the method 'terminate()' manually Method method = source.getClass().getMethod("terminate", new Class[] {}); method.invoke(source, new Object[] {}); }
希望这有助于某人。
也许使用接口和java.lang.reflect.Proxy
会适合你的喜好。 使用一个InvocationHandler
来查找和调用目标类上的相关方法。 (请注意,如果您这样做,您所拥有的任何移动代码安全性将会被击穿。)
如果需要投射的类实现Serializable,那么:
private <T> T castObj(Object o) throws IOException, ClassNotFoundException { if (o != null) { ByteArrayOutputStream baous = new ByteArrayOutputStream(); { ObjectOutputStream oos = new ObjectOutputStream(baous); try { oos.writeObject(o); } finally { try { oos.close(); } catch (Exception e) { } } } byte[] bb = baous.toByteArray(); if (bb != null && bb.length > 0) { ByteArrayInputStream bais = new ByteArrayInputStream(bb); ObjectInputStream ois = new ObjectInputStream(bais); T res = (T) ois.readObject(); return res; } } return null; }
用法:
Object o1; // MyObj from different class loader MyObj o2 = castObj(o1);
没有可能投在不同的类加载器。
你有Gson这个解决方法 ,例如铸造对象YourObject(对象是一个YourObject类,但在其他classLoader):
Object o = ... Gson gson = new Gson(); YourObject yo = gson.fromJson(gson.toJson(o), YourObject.class);
我使用这个解决方法,因为我在WebApp(在Tomcat上)编译任何Java代码。 此解决方法在生产中运行。
这是我到达的一个旧post,因为我想做几乎相同的事情,但它的一个更简单的版本…
它实际上工作,如果Foo和加载类(在我的情况下从另一个包中的.java类文件)扩展相同的类,例如AbstractTestClass。
代码片段:
public AbstractTestClass load(String toLoad) { try{ Class test = Class.forName("testsFolder.testLoadable"); Constructor ctorlist[] = test.getDeclaredConstructors(); for(Constructor aConstructor : ctorlist){ if(...){// find the good constructor Object loadedTest = aConstructor.newInstance(new Object[]{/*params*/}); return (AbstractTestClass) test; } } }catch(...){} return new defaultTestClass(); }
这样我可以将加载的类插入一个ArrayList<AbstractTestClass>
。