Создавать Pojo во время выполнения и после сохранения pojo на диске, выдавая ошибку, когда класс сокращен? - PullRequest
0 голосов
/ 31 октября 2018

Со ссылкой на следующую ссылку я создал классы во время выполнения, http://blog.javaforge.net/post/31913732423/howto-create-java-pojo-at-runtime-with-javassist.I использовал cc.writeFile("//path") непосредственно перед или сразу после того, как вы позвонили cc.toClass() класс был сохранен в указанном месте. но выдает ошибку, как показано ниже, не удается продолжить после cc.writeFile ().

Исключение в потоке "main" java.lang.RuntimeException: toBytecode (): EmployeeEntity было удалено.

1 Ответ

0 голосов
/ 31 октября 2018

При взгляде на исходный код кажется, что проблема вызвана тем, что оба значения, wasChanged и pruned, true.

.

На самом деле автоматическое сокращение должно быть отключено по умолчанию, по крайней мере, в последних версиях. Но если файл класса был удален, он не должен позволять последующие изменения. Это приводит к выводу, что вы не могли изменить промежуточный объект CtClass, поэтому ошибка не на вашей стороне. Поиск в файле wasChanged вхождений обнаруживает, что когда-либо было забыто установить для него значение false.

Так что же происходит,

  • Вы устанавливаете строящийся класс, который превращает wasChanged в true.
  • Вы вызываете toClass(), который, в свою очередь, вызывает toBytecode, который установит pruned и frozen на true, запрещая дальнейшие изменения, но забывает установить wasChanged на false.
  • Вы вызываете writeFile, который также вызывает toBytecode, который теперь определяет, что файл был изменен, в соответствии с флагом, который он никогда не сбрасывает, и выдает исключение, так как класс был удален.

Если вы поменяете местами toClass() и writeFile, логика останется прежней, так как это тот факт, что оба они вызывают toBytecode внутри, что не может быть вызвано дважды, учитывая поведение, описанное выше.

У вас есть несколько вариантов.

  • Вы можете позвонить debugWriteFile​(path) до , позвонив toClass(), так как debugWriteFile задокументировано как «не сокращать и не замораживать класс после записи файла класса» .

  • Вы можете позвонить stopPruning(true), прежде чем звонить writeFile или toClass. Как упомянуто выше, обрезка должна быть по умолчанию выключена.

  • Вы можете позвонить toBytecode() непосредственно себе и позвонить только один раз. Тогда ...

    • Получив байтовый массив, вы можете просто записать его в файл (например, Files.write(Paths.get(pathString), byteArray).

    • Чтобы использовать этот существующий байтовый массив для создания класса, вы можете использовать собственный загрузчик классов или использовать MethodHandles.lookup().defineClass(array), если вы используете Java 9 или новее и создаете класс в своем собственный пакет.

    Это может быть немного сложнее, но поскольку это создает байты файла класса только один раз, это наиболее эффективное решение.

...