Java 动态类加载器抛出 ClassNotFoundException
Java Dynamic classloader throws ClassNotFoundException
我有一个项目有自己的 classloader。
但是我在加载一些 classes 时遇到了一个奇怪的问题。
基本上是这样的:
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
// do some magic
return myBrandNewClas;
}
但是发生的是,即使返回 class,Class.forName(...) 仍然抛出 ClassNotFoundException (示例可在 here 中找到)。
另一个信息:返回的 class' 名称与请求的 class 名称不同。
我开始怀疑它是不是JVM的安全锁(在Oracle JVM中测试过)。
谢谢!
forName 的代码是原生的,因此很难看到,但是我会说名称已经过检查,因为传递正确的名称是有效的:
public class BBB
{
public static class a {
}
private static class MyCL extends ClassLoader
{
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
System.out.println("Hi, " + a.class.getName());
return a.class;
}
}
public static void main(String[] args) throws ClassNotFoundException
{
MyCL cl = new MyCL();
System.out.println(Class.forName("com.asg.util.BBB$a", true, cl));
}
我可以通过将 class 重命名为所需的 class 名称来解决问题。
import javassist.ClassPool;
import javassist.CtClass;
public class AAA
{
public static class B
{
@Override
public String toString()
{
return "B";
}
}
private static class X extends ClassLoader
{
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
try
{
if ("A".equals(name))
{
ClassPool cp = ClassPool.getDefault();
CtClass clazz = cp.get("AAA$B");
clazz.setName("A");
return clazz.toClass();
}
return super.loadClass(name, resolve);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws Exception
{
X x = new X();
System.out.println(Class.forName("A", true, x).newInstance().toString());
}
}
目前为止效果很好。现在我将这段代码放入我的项目中。
我有一个项目有自己的 classloader。 但是我在加载一些 classes 时遇到了一个奇怪的问题。
基本上是这样的:
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
// do some magic
return myBrandNewClas;
}
但是发生的是,即使返回 class,Class.forName(...) 仍然抛出 ClassNotFoundException (示例可在 here 中找到)。
另一个信息:返回的 class' 名称与请求的 class 名称不同。
我开始怀疑它是不是JVM的安全锁(在Oracle JVM中测试过)。
谢谢!
forName 的代码是原生的,因此很难看到,但是我会说名称已经过检查,因为传递正确的名称是有效的:
public class BBB
{
public static class a {
}
private static class MyCL extends ClassLoader
{
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
System.out.println("Hi, " + a.class.getName());
return a.class;
}
}
public static void main(String[] args) throws ClassNotFoundException
{
MyCL cl = new MyCL();
System.out.println(Class.forName("com.asg.util.BBB$a", true, cl));
}
我可以通过将 class 重命名为所需的 class 名称来解决问题。
import javassist.ClassPool;
import javassist.CtClass;
public class AAA
{
public static class B
{
@Override
public String toString()
{
return "B";
}
}
private static class X extends ClassLoader
{
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
try
{
if ("A".equals(name))
{
ClassPool cp = ClassPool.getDefault();
CtClass clazz = cp.get("AAA$B");
clazz.setName("A");
return clazz.toClass();
}
return super.loadClass(name, resolve);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws Exception
{
X x = new X();
System.out.println(Class.forName("A", true, x).newInstance().toString());
}
}
目前为止效果很好。现在我将这段代码放入我的项目中。