17

在 Java 中,是否可以在应用程序运行时动态创建类定义,然后创建该类的对象?

例如,一个正在运行的应用程序将读入一个文本文件,该文件包含要包含在新类中的类成员列表。然后,应用程序将根据成员列表定义一个类定义,然后实例化它。

4

11 回答 11

11

是的,理论上可以这样做,您的类文件是字节码,最后是字节数组!然后,您可以使用方法 defineClass(String, byte[], int, int) 来获取可用于通过反射实例化对象的 Class 实例。

在实践中,您可以使用CGLibjavaassist 之类的东西。

您还可以使用长方法在文件中生成 java 代码,调用编译器,然后加载文件。

于 2009-04-23T13:56:42.910 回答
2

您可以使用ASM动态生成类

于 2009-04-23T13:59:07.383 回答
1

为此,您可以将新类的代码写入文件,然后在该文件上调用 Java 编译器并使用类加载器将该类动态加载到正在运行的应用程序中。Apache Tomcat 为其 JSP 页面执行此操作;它获取代码,对其进行一些更改,将其包装在类中间的 try/catch 块中,然后将其写入文件系统,编译它,并使用类加载器获取并起诉它以服务请求。

于 2009-04-23T13:54:21.200 回答
1

当然有可能。例如见这篇文章

于 2009-04-23T13:57:07.747 回答
1

我想ASM是 Java 的最低级字节码库。这使得它非常困难,但也非常强大。我建议阅读 ASM 的文档 ( PDF ) 以真正了解 Java 中字节码生成的工作原理。该文档还解释了如何在类加载器中加载字节码(另一个很难做到的话题)。

之后,您可以使用更高级别的库之一,如果它使您的生活更轻松,并了解它们的作用。对于许多情况,例如生成代理,CGLIB非常有用且易于使用。为了获得更多功能,许多人提到了Javassist(我没有使用它 - CGLIB 和 ASM 对我有好处)。

于 2009-04-23T14:22:44.190 回答
1

也许最简单的解决方案(就不需要额外的库而言)是使用 Java 6 附带的Java 编译器 API。您只需能够生成 .java,编译然后执行 Class.forName()。

于 2009-04-23T15:03:05.763 回答
0

也许有点矫枉过正,Apache BCEL(字节码工程库)可用于class在运行时创建文件。

虽然我自己没有尝试过,但可以想象,可以创建一个类,加载它,并在运行时实例化它。

于 2009-04-23T14:00:51.183 回答
0

是的,这是可能的。

您可以通过定义类的主体并使 javassist 编译您的新类,在运行时使用Javassist创建类。

Javassist 有一个自定义编译器,可以根据您的类的定义创建字节码。它有一些特殊的方法来处理事情,但是使用这个库非常容易和直观。

Javassist 用于 JBoss,我认为这是一个很好的参考 :)

使用BCEL也可以实现相同的目的,但是要困难得多(但是通过这种方式,您可以更好地控制正在生成的内容)。

于 2009-04-23T14:00:54.553 回答
0

如果必须的话,您可以使用 JRuby、JPython 或 Groovy 来做类似的事情。

如果你感觉特别受虐,你可以看看BCEL

于 2009-04-23T14:03:33.987 回答
0

如果您想要 Java 和元编程,请使用Groovy

于 2009-04-23T14:09:28.323 回答
0

最近有一个关于内存编译的问题,它应该会给你一些提示,告诉你在你设法生成源代码后该做什么。

于 2009-04-23T16:34:50.867 回答