在 Java 应用程序运行时定义类
在Java中,是否可以在应用程序运行时动态创建类定义,然后创建该类的对象?
例如,正在运行的应用程序将读入一个文本文件,其中包含要包含在新类中的类成员列表。 然后,应用程序将根据成员列表定义一个类定义,然后实例化它。
In Java, is it possible to create a class definition on the fly while an application is running, and then create an object of that class?
For example, a running application would read in a text file that contains a list of class members to include in the new class. The application would then define a class definition based on the list of members, and then insantiate it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
是的,这是可能的。
您可以在运行时通过定义主体来使用 Javassist 创建类类并让 javassist 编译您的新类。
Javassist 有一个自定义编译器,可以根据类的定义创建字节码。 它有一些特殊的方法来处理事情,但是使用这个库非常简单和直观。
Javassist 用于 JBoss 上,我认为这是一个很好的参考:)
使用 BCEL 也可以实现相同的效果,但是它要困难得多(但通过这种方式,您可以更好地控制正在生成的内容)。
Yes, that is possible.
You can create classes with Javassist at runtime by defining the body of the class and making javassist compile your new class.
Javassist has a custom compiler that creates bytecode based on the definition of your class. It has some particular ways to handle things, but it's very easy and intuitive to use this library.
Javassist is used on JBoss, and I think that is a good reference :)
The same can be achieved with BCEL, however it's much harder (but in this way you have more control over what is being generated).
如果必须的话,您可以使用 JRuby、JPython 或 Groovy 做类似的事情。
如果您感觉特别受虐,您可以查看 BCEL。
You could probably do something like that with JRuby, or JPython or Groovy if you must.
If you're feeling particularly masochistic you could look at BCEL.
如果您需要 Java 和元编程,请使用 Groovy。
If you want Java and metaprogramming, use Groovy.
最近有一个关于 内存中编译 应该会给您一些提示,告诉您在成功生成源代码后要做什么。
There was a recent question here regarding in-memory compilation which should give you some hints on what to do after you've managed to generate the source code.
是的,理论上可以这样做,您的类文件是字节代码,最后是字节数组! 然后,您可以使用方法defineClass(String, byte[], int, int)来获取可用于通过反射实例化对象的Class实例。
在实践中,您可以使用诸如 CGLib 或 javaassist。
您还可以使用在文件中生成 java 代码、调用编译器、然后加载文件的长方法。
Yes its possible to do so in theory your class file is byte code which is at the end a byte array! you can then use the method defineClass(String, byte[], int, int) to get a Class instance that can be used to instantiate objects via reflection.
In practice you can use something like CGLib or javaassist.
You can also use the long way of generating the java code in a file, invoking the compiler, then loading the file.
您可以使用 ASM 动态生成类
You can dynamically generate classes using ASM
为此,您可以将新类的代码写入文件,然后在该文件上调用 Java 编译器,并使用类加载器将该类动态加载到正在运行的应用程序中。 Apache Tomcat 对其 JSP 页面执行此操作; 它获取代码,对其进行一些更改,将其包装在类中间的 try/catch 块中,然后将其写入文件系统,编译它,并使用类加载器获取并起诉它来服务请求。
You can do this by writing the code for your new class out to a file, then invoking the Java compiler on that file and using a classloader to dynamically load that class into your running application. Apache Tomcat does this for its JSP pages; it takes the code, makes some changes to it, wraps it in a try/catch block in the middle of a class, which it then writes to the filesystem, compiles it, and uses a classloader to get and sue it to serve requests.
当然有可能。 例如,请参阅这篇文章。
Sure it is possible. See for example this article.
我认为 ASM 是 Java 的最低级别字节码库。 这使得它非常困难,但也非常强大。 我建议阅读 ASM 的文档 (PDF) 以真正了解字节码生成的方式在Java作品中。 该文档还解释了如何在类加载器中加载字节码(另一个很难正确完成的主题)。
之后,您可以使用更高级别的库之一(如果它能让您的生活更轻松)并了解它们的作用。 对于许多情况,例如生成代理,CGLIB 非常有用且易于使用。 为了获得更多功能,许多人提到了 Javassist (我没有没用过它 - CGLIB 和 ASM 对我很有好处)。
ASM is the lowest level bytecode library for Java, I suppose. That makes it very hard but also very powerful. I recommend reading ASM's documentation (PDF) to really understand how bytecode generation in Java works. That documentation also explains how to load the bytecode in the class loader (another hard topic to do right).
After that you may use one of the higher level libraries, if it makes your life easier, and understand what they do. For many cases, such as generating proxies, the CGLIB is useful and simple to use. For more power, many have mentioned Javassist (I haven't used it - CGLIB and ASM have been good for me).
也许最简单的解决方案(就不需要额外的库而言)是使用 Java 6 附带的 Java 编译器 API。您只需生成 .java、编译然后执行 Class.forName()。
Perhaps the simplest solution (in terms of not requiring extra libraries) would be to use the Java compiler API that comes with Java 6. You just just be able to generate the .java, compile and then perform a Class.forName().
也许有点过头了,Apache BCEL(字节代码工程库)可用于创建
class 文件。
尽管我自己没有尝试过,但可以想象,人们可以创建一个类,加载它,并在运行时实例化它。
Perhaps a little overkill, the Apache BCEL (Byte Code Engineering Library) can be used to create
class
files during runtime.Although I haven't tried it myself, conceivably, one could then create a class, load it, and instantiate it during runtime.