在 Java 应用程序运行时定义类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/781805/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:46:02  来源:igfitidea点击:

Defining a class while a Java application is running

javaon-the-flyruntime-compilation

提问by Lehane

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?

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

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.

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

采纳答案by MahdeTo

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.

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

In practice you can use something like CGLibor javaassist.

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

You can also use the long way of generating the java code in a file, invoking the compiler, then loading the file.

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

回答by Boune

You can dynamically generate classes using ASM

您可以使用ASM动态生成类

回答by kgiannakakis

Sure it is possible. See for example this article.

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

回答by Eli Courtwright

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.

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

回答by Esko Luontola

ASMis 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).

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

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 CGLIBis 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).

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

回答by Brian Agnew

Perhaps the simplestsolution (in terms of not requiring extra libraries) would be to use the Java compiler APIthat comes with Java 6. You just just be able to generate the .java, compile and then perform a Class.forName().

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

回答by Phil M

There was a recent question here regarding in-memory compilationwhich should give you some hints on what to do after you've managed to generate the source code.

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

回答by coobird

Perhaps a little overkill, the Apache BCEL(Byte Code Engineering Library) can be used to create classfiles during runtime.

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

Although I haven't tried it myself, conceivably, one could then create a class, load it, and instantiate it during runtime.

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

回答by Edison Gustavo Muenz

Yes, that is possible.

是的,这是可能的。

You can create classes with Javassistat runtime by defining the body of the class and making javassist compile your new class.

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

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 有一个自定义编译器,可以根据类的定义创建字节码。它有一些特殊的处理方式,但使用这个库非常简单和直观。

Javassist is used on JBoss, and I think that is a good reference :)

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

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).

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

回答by Evan

You could probably do something like that with JRuby, or JPython or Groovy if you must.

如果必须,您可能可以使用 JRuby、JPython 或 Groovy 执行类似的操作。

If you're feeling particularly masochistic you could look at BCEL.

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