Java: Как загрузить класс, сохраненный в качестве байта [] в JVM?
Если вы сериализовали весь файл .class в файл byte [], и если имя класса известно (передано вместе с байтом []), как вы можете преобразовать byte [] → Class → then load это в JVM, чтобы впоследствии использовать его, вызывая Class.forName()?
Примечание:
Я делаю это, потому что я отправил .class на другой хост, а JVM-хост не знает об этом .class.
Ответы
Ответ 1
На самом деле я использую что-то подобное прямо сейчас в тесте, чтобы дать набор определений классов как 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);
}
}
Ответ 2
Используйте метод defineClass (String, byte [], int, int) из ClassLoader
Ответ 3
Разверните 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);
}
}
Ответ 4
Хорошо, так вот что я сделал:
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;
}
}
Ответ 5
Ответ Alex правильный, но если у вас есть отношения наследования между классами, вам нужно сначала загрузить родительский класс. В противном случае загрузчик классов не сможет определить его.