我试图了解 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 日
我应该提到的一件事......我正在使用Socket
并ObjectInputStream
接收“本地”发送到“远程”的消息。我在ObjectInputStream
“远程”端创建了一个自定义扩展并覆盖了protected Class<?> resolveClass(ObjectStreamClass)
. 这是当传入消息包含尚未加载的类实例时我的“远程”JVM 收到的第一个通知。我有另一个用于传递类定义的套接字,因此当第一个套接字接收到尚未加载的类的实例时,它会通过第二个套接字从“本地”JVM 请求该类的定义。
当我的自定义ObjectInputStream.resolveClass(ObjectStreamClass)
通过ObjectStreamClass
返回数组类型的类名(名称看起来像[Lsome.ClassName;
)时,就会出现问题。我可以很容易地解析出基级类型some.ClassName
并首先加载它——这是在对 的调用中完成的NetworkClassLoader.getInstance.loadClass()
,在这里我得到byte[]
基级类的一个,然后使用它defineClass()
在该方法调用中进行调用。
我现在明白了,您可能无法获得byte[]
数组类型的类定义,所以这让我试图弄清楚如何找到Class<?>
数组类型的实例并返回它。这是我在“远程”JVM 的消息接收resolveClass
中自定义的方法的代码:ObjectInputStream
Socket
@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();
}