Java: How to load Class stored as byte[] into the JVM?
If one has serialized the entire .class file into byte[], and assuming the name of the class is known (passed along with the byte[]), how do you convert byte[] -> Class -> then load it to the JVM so that I could later use it by calling the Class.forName()?
NOTE: I'm doing this because I sent the .class over to another host, and the host's JVM doesn't know about this .class.
Solution 1:
I'm actually using something like this right now in a test to give a set of Class definitions as byte[] to a 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);
}
}
Solution 2:
Use the defineClass(String, byte[], int, int) method from ClassLoader
Solution 3:
Extend ClassLoader
and then implement the necessary call to obtain your byte[]
inside the method defineClass()
. Conversely you can do this in findClass()
. You'll thus load this ClassLoader at the beginning or employ it when you need class definitions via your array.
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);
}
}
Solution 4:
Okay, so here's what I did:
public class AgentClassLoader extends ClassLoader
{
public void loadThisClass(ClassByte classByte_)
{
resolveClass(defineClass(classByte_.getName(),
classByte_.getBytes(),
0,
classByte_.getBytes().length));
}
}
I hope that loads the class into JVM? If this really works, why didn't Java implementator make both defineClass and resolveClass public methods? I really wonder what they were thinking. Anyone can enlighten me?
Just for completeness, here's 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;
}
}