Подтвердить что ты не робот

Java: Как загрузить класс, сохраненный в качестве байта [] в JVM?

Если вы сериализовали весь файл .class в файл byte [], и если имя класса известно (передано вместе с байтом []), как вы можете преобразовать byte [] → Class → then load это в JVM, чтобы впоследствии использовать его, вызывая Class.forName()?

Примечание: Я делаю это, потому что я отправил .class на другой хост, а JVM-хост не знает об этом .class.

4b9b3361

Ответ 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 правильный, но если у вас есть отношения наследования между классами, вам нужно сначала загрузить родительский класс. В противном случае загрузчик классов не сможет определить его.