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.
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
wasChanged
to true
.toClass()
, which in turn invokes toBytecode
, which will set pruned
and frozen
to true
, disallowing further modifications, but forgets to set wasChanged
to false
.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…
Once you have the byte array, you can simply write it to a file (e.g. Files.write(Paths.get(pathString), byteArray)
.
To use this existing byte array to create the class, you may use your own class loader or use MethodHandles.lookup().defineClass(array)
, if you are under Java 9 or newer and create a class in your own package.
This might be a bit more complicated, but since this constructs the class file bytes only once, it’s the most efficient solution.