Java:如何将存储为 byte[] 的类加载到 JVM 中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1781091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: How to load Class stored as byte[] into the JVM?
提问by sivabudh
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()?
如果已经将整个 .class 文件序列化为 byte[],并且假设类的名称是已知的(与 byte[] 一起传递),那么您如何转换 byte[] -> Class -> 然后将其加载到JVM 以便我以后可以通过调用 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.
注意:我这样做是因为我将 .class 发送到另一个主机,而主机的 JVM 不知道这个 .class。
采纳答案by Alex Miller
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);
}
}
回答by Jé Queue
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.
扩展ClassLoader
然后实现必要的调用以获取您的byte[]
内部方法defineClass()
。相反,您可以在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);
}
}
回答by Matt
Use the defineClass(String, byte[], int, int) method from ClassLoader
使用来自的defineClass(字符串,字节[],INT,int)方法类加载器
回答by sivabudh
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?
我希望将类加载到 JVM 中?如果这真的有效,为什么 Java 实现者不同时创建 defineClass 和 resolveClass 公共方法?我真的很想知道他们在想什么。任何人都可以启发我吗?
Just for completeness, here's ClassByte
只是为了完整性,这里是 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;
}
}
回答by marting
The answer of Alex is correct but if you have inheritance relationship between classes you need to make sure you load the parent class first. Otherwise the class loader won't be able to define it.
Alex 的答案是正确的,但是如果类之间有继承关系,则需要确保首先加载父类。否则类加载器将无法定义它。