2

我试图了解 Java 类加载器是如何工作的,特别是defineClass(String,byte[],int,int)方法。假设我想为NonIntrinsicType. 我知道我可以找到 *.class 文件NonIntrinsicType,将其内容序列化为byte[]被调用的bytes,然后调用defineClass(null,bytes,0,bytes.length).

我无法理解的奇怪情况是,我怎样才能获得类似byte[]的类定义[LNonIntrinsicType- 换句话说,如果我的应用程序请求 的实例的类定义NonIntrinsicType[],我没有 *.class 文件对应于此类类型。我如何获得byte[]这种类型的定义?

你可能想知道我为什么要这样做。我基本上是在尝试创建一个网络类加载器,其中有一个在其类路径上具有类定义的“本地”JVM,以及一个在其类路径上没有上述类定义的“远程”JVM。“远程”遇到NonIntrinsicType[]该类类型的实例并从“本地”请求定义,但我的“本地”JVM 找不到 的类文件NonIntrinsicType[],因此无法为byte[]“远程”提供类定义。

添加于 2010 年 9 月 7 日

我应该提到的一件事......我正在使用SocketObjectInputStream接收“本地”发送到“远程”的消息。我在ObjectInputStream“远程”端创建了一个自定义扩展并覆盖了protected Class<?> resolveClass(ObjectStreamClass). 这是当传入消息包含尚未加载的类实例时我的“远程”JVM 收到的第一个通知。我有另一个用于传递类定义的套接字,因此当第一个套接字接收到尚未加载的类的实例时,它会通过第二个套接字从“本地”JVM 请求该类的定义。

当我的自定义ObjectInputStream.resolveClass(ObjectStreamClass)通过ObjectStreamClass返回数组类型的类名(名称看起来像[Lsome.ClassName;)时,就会出现问题。我可以很容易地解析出基级类型some.ClassName并首先加载它——这是在对 的调用中完成的NetworkClassLoader.getInstance.loadClass(),在这里我得到byte[]基级类的一个,然后使用它defineClass()在该方法调用中进行调用。

我现在明白了,您可能无法获得byte[]数组类型的类定义,所以这让我试图弄清楚如何找到Class<?>数组类型的实例并返回它。这是我在“远程”JVM 的消息接收resolveClass中自定义的方法的代码:ObjectInputStreamSocket

@Override
protected Class<?> resolveClass(ObjectStreamClass osc) 
        throws IOException, ClassNotFoundException{
    try {
        return super.resolveClass(osc);
    } catch (Exception e){}

    String name = osc.getName();
    boolean array = name.contains("[L");

    if(array) name = name.replace("[L","").
            replace("[","").replace(";","");

    Class<?> c = NetworkClassLoader.getInstance().loadClass(name);
    if(!array) return c;

    //If it's an array type, how do I obtain its corresponding
    //Class<?> and return it here?

    throw new ClassNotFoundException();
}
4

5 回答 5

4

您不需要为[LType. 如果你有一个Class,你可以用反射创建一个该类的数组:

Object array = Array.newInstance(yourClass, dimensions);
于 2012-09-06T23:25:12.787 回答
2

您无法控制数组的加载,因为它们没有被加载。没有什么可以加载的。数组没有类。没有类定义。没有字节[]。

于 2012-09-06T23:17:16.857 回答
0

可以做到这一点的唯一方法是修补 JVM 的 defineClass(...) 方法以查找所需的类,然后将它们存储起来以备后用。

于 2012-09-06T23:37:43.337 回答
0

数组类由 JVM 创建,无需调用defineClass().

请参阅http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.3.3

于 2012-09-07T02:50:17.457 回答
0

来自ClassLoader javadoc的摘录:

数组类的类对象不是由类加载器创建的,而是根据 Java 运行时的要求自动创建的。Class.getClassLoader() 返回的数组类的类加载器与其元素类型的类加载器相同;如果元素类型是原始类型,则数组类没有类加载器。

了解如何要求您的类加载器为[LNonIntrinsicType. 感觉就像你在做一些定制的事情。如果你能更详细地描述你在做什么,我们就能更好地理解你的问题。当您的类加载器被要求定义时,调用堆栈是[LNonIntrinsicType什么?

于 2012-09-07T02:55:03.800 回答