我试图了解Java类加载器的工作原理,特别是defineClass(String,byte[],int,int)
方法。假设我想加载NonIntrinsicType
的类定义。我知道我可以找到NonIntrinsicType
的* .class文件,将其内容序列化为名为byte[]
的{{1}},然后调用bytes
。
我难以理解的奇怪情况是,如何获得defineClass(null,bytes,0,bytes.length)
类byte[]
的类定义 - 换句话说,如果我的应用程序请求类的定义[LNonIntrinsicType
的实例,我没有与此类类型对应的* .class文件。如何获得此类型定义的NonIntrinsicType[]
?
你可能想知道我为什么要这样做。我基本上试图创建一个网络类加载器,它的“本地”JVM在其类路径上有类定义,而“远程”JVM在其类路径上没有上述类定义。 “Remote”遇到byte[]
的实例,并从“Local”请求该类类型的定义,但我的“Local”JVM找不到NonIntrinsicType[]
的类文件,因此无法将类定义NonIntrinsicType[]
提供给“远程”。
已添加9/7/2010
我应该提到的一件事......我正在使用byte[]
和Socket
来接收“本地”发送到“远程”的消息。我在“远程”一侧创建了ObjectInputStream
的自定义扩展程序,并覆盖了ObjectInputStream
。当传入消息包含尚未加载的类的实例时,这是我的“远程”JVM获得的第一个通知。我有另一个套接字用于传递类定义,所以当第一个套接字接收到一个尚未加载的类的实例时,它通过第二个套接字从“本地”JVM请求该类的定义。
当我的自定义protected Class<?> resolveClass(ObjectStreamClass)
传递ObjectInputStream.resolveClass(ObjectStreamClass)
并返回数组类型的类名(名称看起来像ObjectStreamClass
)时,会出现问题。我可以轻松地解析基类级别[Lsome.ClassName;
并首先加载它 - 这是在调用some.ClassName
时完成的,我在这里获得基类级别的NetworkClassLoader.getInstance.loadClass()
然后用它在该方法调用中调用byte[]
。
我现在明白你可能无法获得数组类型的类定义的defineClass()
,因此这让我试图弄清楚如何找到数组类型的byte[]
实例并返回它。以下是我在“远程”JVM的邮件接收Class<?>
上的自定义resolveClass
中ObjectInputStream
方法的代码:
Socket
答案 0 :(得分:3)
您不需要为[LType
创建定义。如果您有Class
,则可以使用反射创建该类的array:
Object array = Array.newInstance(yourClass, dimensions);
答案 1 :(得分:2)
您无法控制数组的加载,因为它们未加载。没有什么可加载的。数组没有类。没有课程定义。没有字节[]。
答案 2 :(得分:0)
唯一可行的方法是修补JVM的defineClass(...)方法以查找所需的类,然后将它们存储起来供以后使用。
答案 3 :(得分:0)
数组类由JVM创建,无需调用defineClass()
。
请参阅http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.3.3
答案 4 :(得分:0)
摘自ClassLoader javadoc:
数组类的类对象不是由类加载器创建的,而是 是根据Java运行时的需要自动创建的。班级 数组类的加载器,由Class.getClassLoader()返回 与元素类型的类加载器相同;如果元素类型 是一个原始类型,然后数组类没有类加载器。
理解你的类加载器如何被要求为[LNonIntrinsicType
创建一个类会很有趣。感觉就像你在做一些自定义的事情。如果您能够更详细地描述您正在做什么,我们可以更好地了解您的问题。当要求您的类加载器定义[LNonIntrinsicType
时,调用堆栈是什么?