The November issue of the JavaRanch Journal has an article by yours truely about Creating Java classes at runtime for evaluating numerical expressions. You can check it out here, and if you have comments or question, feel free to discuss them in this thread.
Very cool! I had no idea Javassist was so easy to get started with.
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Great article. I have one question regarding this article. You mentioned at the end of this article that there are Low Level API to do the same thing. Can you tell me how can i create classes on runtime without using Javaassist ?
Javassist's low-level APIs can be used to create class files if you know your way around JVM bytecode (I've yet to meet anyone who does, but the API makes it possible).
What requirement prompts you to ask for a way to create classes without using Javassist?
I just read your article and out of curiosity asked this question. However, we may need to use low level API's in a condition where adding new library file (like Javaassist) is not permitted. This unsually happens when you are working on a large project and management will not allow any third-party libs.
Secondly, can we do this by having custom implementation of Class Loader ?
Java 6 has an API for working with the compiler. If you save the source code for the complete class (and give it a unique name) then you can create actual class files at runtime. If the class implements some specific interface, you can access it after compilation through something like
I actually read that article that you have posted but I was trying to execute the examples on Netbeans but I am getting certain runtime errors. Please do have a look.
Exception in thread "main" java.lang.NoClassDefFoundError: Evaluator
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
at javassist.ClassPool$LocalClassLoader.loadClass(ClassPool.java:353)
at javassist.ClassPool.writeAsClass(ClassPool.java:404)
at javassist.CtClass.toClass(CtClass.java:755)
at assist.Example2.main(Example2.java:23)
Caused by: java.lang.ClassNotFoundException: Evaluator
at java.lang.ClassLoader.findClass(ClassLoader.java:358)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 8 more
Java Result: 1
Please do help asap. I need to use this concept in a tool that I am building.
I'm not familiar with NetBeans, but you need to make sure that all required classes (including Evaluator) are in its classpath when it tries to run the code.
It may be easier to get this to run on the command line using something like:
java -classpath javassist-3.4.jar;. Example1
(assuming you're on Windows, otherwise use : instead of ; )
Thanks for the great article, really nice code that works like a charm. I use it for genetic programming, and already integrated Example1 successfully. Seems to calculate complex equations faster than most other interpreters I've tested! However, I have problems when trying to intergrate Example2 to my project. It seems that it just won't compile for me outside the standard package:
Exception in thread "main" javassist.CannotCompileException: by java.lang.NoClassDefFoundError: Evaluator
at javassist.ClassPool.toClass(ClassPool.java:1099)
at javassist.ClassPool.toClass(ClassPool.java:1042)
at javassist.ClassPool.toClass(ClassPool.java:1000)
at javassist.CtClass.toClass(CtClass.java:1140)
at tiny.Example2.main(Example2.java:25)
Caused by: java.lang.NoClassDefFoundError: Evaluator
at java.lang.ClassLoader.defineClass1(Native Method)
.....
What I did:
1. set up a new project with only the two files Evaluator.java and Example2.java in the default package, set classpath to javassist, and it works fine
2. used the same files (added only package definitions) in an existing project - and I get the error message. Build path to javassist exists.
Help would be highly appreciated, this is driving me crazy for one day now...
Working on Windows 7 with Eclipse by the way. Thanks in advance!
Me again, solved my issue. I'm posting it in case someone else runs into the same problem. The solution is quite straightforward, a shame that I didn't see it for so long. If you use the Example2 code in a package (as one should do), one must refer to the full qualified name when referring to Evaluator. Assuming that you use all files in a package called "tes", the according command is:
An approach to avoid the above described java.lang.NoClassDefFoundError:
When referring to an existing class or package get the meta information from a textual reference to this class directly instead of using String literals.
Another advantage is that refactorings (rename or move to another package) of the referenced class is applied to the class name (and import declarations if needed) in the code automatically.