Search code examples
hibernateclassdynamicbytecode

Create Pojo at runtime and after saving pojo on to the disk throwing an error as class pruned?


With reference to the following link, I have created the classes at run time, http://blog.javaforge.net/post/31913732423/howto-create-java-pojo-at-runtime-with-javassist.I have used cc.writeFile("//path") right before or right after you call cc.toClass() class has been stored at the location specified. but throwing an error as below unable to continue after cc.writeFile().

Exception in thread "main" java.lang.RuntimeException: toBytecode(): EmployeeEntity was pruned.


Solution

  • When looking at the source code, it seems, that the problem is caused by the fact that both, wasChanged and pruned, are true.

    Actually, automatic pruning should be off by default, at least on recent versions. But if the class file has been pruned, it should not allow subsequent modifications. This leads to the conclusion that you can’t have modified the CtClass object in-between, so the error is not on your side. Searching for occurrences of wasChanged in the file reveals that it has been forgotten to ever set it to false.

    So what happens, is

    • You set up the class under construction, which turns wasChanged to true.
    • You call toClass(), which in turn invokes toBytecode, which will set pruned and frozen to true, disallowing further modifications, but forgets to set wasChanged to false.
    • You call writeFile, which will also call toBytecode, which now detects that the file has been modified, according to the flag that it never resets, and throws an exception, as the class has been pruned.

    If you swap toClass() and writeFile, the logic stays the same, as it is the fact that both call toBytecode internally, which can’t be invoked twice, given the behavior described above.

    You have several options.

    • You can call debugWriteFile​(path) before calling toClass(), as debugWriteFile is documented to “not prune or freeze the class after writing the class file”.

    • You can call stopPruning(true) before calling writeFile or toClass. As mentioned above, pruning should be even off by default.

    • You may call toBytecode() directly yourself and call it only once. Then…

      This might be a bit more complicated, but since this constructs the class file bytes only once, it’s the most efficient solution.