Java: получение байт-кода класса во время выполнения из той же JVM - PullRequest
12 голосов
/ 09 ноября 2010

Относится к: Есть ли способ получить байт-код для класса во время выполнения?

Я добавляю долговечность в Clojure и, наконец, я готов добавить функции. В Clojure функции байтово скомпилированы в классы с методами invoke (среди прочих). Таким образом, функции первого класса. Чтобы сделать их долговечными, мне нужно сериализовать и десериализовать эти классы. Как получить байт-код для класса, не имея доступа к файлу .class?

Пожалуйста, исправьте меня, если я ошибаюсь, но использование агента требует создания отдельной виртуальной машины с агентом, подключающимся к первой виртуальной машине. Мне нужно сделать это с той же виртуальной машины.

Недостаточно использовать Serializable для установки и получения объекта Class. После десериализации мне нужно загрузить класс, и при последующих экземплярах ВМ может возникнуть конфликт имен классов. Мне нужно изменить байт-код, чтобы переименовать класс во что-то уникальное во время десериализации / загрузки класса.

Ответы [ 3 ]

5 голосов
/ 09 ноября 2010

Вы можете написать свой собственный ClassLoader и взломать схему, которая записывает байт-код при загрузке классов.

Вам потребуется переопределить findClass, чтобы найти файл класса самостоятельно, загрузить его в памятьсохраните данные где-нибудь (для последующей сериализации), затем вызовите defineClass, чтобы определить этот класс в JVM.

3 голосов
/ 09 ноября 2010

Если вы не запускаете код через хитрый загрузчик классов, вы должны иметь возможность сделать что-то вроде этого:

Class<?> clazz = ....
String className = clazz.getCanonicalName();  // e.g. "foo.Bar"
String resourceName = ... // map className to a resource name; e.g. "/foo/Bar.class" 
InputStream is = clazz.getClassLoader.getResourceAsStream(resourceName);

Это дает вам указатель на содержимое файла ".class" ... если его можно найти.

Предостережения. Некоторые загрузчики классов могут:

  • вообще не разрешать открывать ресурсы ".class",
  • даст вам зашифрованный поток байт-кода или
  • дает вам байт-коды, которые не совсем то, что выполняется, из-за некоторого преобразования на лету, выполняемого загрузчиком классов.

Если этот подход не работает, у вас практически нет выбора, потому что JVM не предоставляет способ доступа к фактическим загруженным байт-кодам.

1 голос
/ 20 июля 2012

Вы также можете использовать Java Instrumentation API для этого. Вы получаете доступ к байтам файла класса перед вызовом defineClass. Вы также можете изменить их!

...