.classファイル全体をbyte []にシリアル化し、クラスの名前がわかっている(byte []とともに渡される)と仮定した場合、byte []-> Class->をどのように変換し、それをにロードしますか。後でClass.forName()を呼び出して使用できるようにJVM?
注:これを行っているのは、.classを別のホストに送信し、ホストのJVMがこの.classを認識していないためです。
私は実際にテストでこのようなものを使用して、クラス定義のセットをbyte []としてClassLoaderに提供しています。
public static class ByteClassLoader extends URLClassLoader {
private final Map<String, byte[]> extraClassDefs;
public ByteClassLoader(URL[] urls, ClassLoader parent, Map<String, byte[]> extraClassDefs) {
super(urls, parent);
this.extraClassDefs = new HashMap<String, byte[]>(extraClassDefs);
}
@Override
protected Class<?> findClass(final String name) throws ClassNotFoundException {
byte[] classBytes = this.extraClassDefs.remove(name);
if (classBytes != null) {
return defineClass(name, classBytes, 0, classBytes.length);
}
return super.findClass(name);
}
}
ClassLoader からdefineClass(String、byte []、int、int)メソッドを使用します
ClassLoader
を拡張してから、メソッドdefineClass()
内で_byte[]
_を取得するために必要な呼び出しを実装します。逆に、これはfindClass()
で行うことができます。したがって、このClassLoaderを最初にロードするか、配列を介してクラス定義が必要なときに使用します。
_public class ByteArrayClassLoader extends ClassLoader {
public Class findClass(String name) {
byte[] ba = /* go obtain your byte array by the name */;
return defineClass(name,ba,0,ba.length);
}
}
_
さて、これが私がしたことです:
public class AgentClassLoader extends ClassLoader
{
public void loadThisClass(ClassByte classByte_)
{
resolveClass(defineClass(classByte_.getName(),
classByte_.getBytes(),
0,
classByte_.getBytes().length));
}
}
クラスをJVMにロードすることを望みますか?これが本当に機能するのなら、なぜJava実装者はdefineClassとresolveClassの両方のパブリックメソッドを作成しなかったのですか?彼らが何を考えていたのか本当に疑問に思います。誰でも私を啓発できますか?
完全を期すために、ここにClassByteがあります
import Java.io.Serializable;
public class ClassByte implements Serializable
{
private String name;
private byte[] bytes;
ClassByte(String name_, byte[] bytes_)
{
name = name_;
bytes = bytes_;
}
public String getName()
{
return name;
}
public byte[] getBytes()
{
return bytes;
}
}
Alexの答えは正しいですが、クラス間に継承関係がある場合は、最初に親クラスをロードする必要があります。そうしないと、クラスローダーはそれを定義できません。