【问题标题】:java in-memory on-the-fly class compilation (and loading)java in-memory on-the-fly类编译(和加载)
【发布时间】:2009-11-24 20:22:01
【问题描述】:

我想重温一个关于类的内存“编译”的老问题。自从我问(并且得到了一些回答)以来,大约一年过去了 1/2,我想重新提出这个问题,看看是否会出现新的问题(所以不,我不认为这是重复的) .

老问题可以在这里找到:On-the-fly, in-memory java code compilation for Java 5 and Java 6 - 我建议在回答这个问题之前阅读它(和答案)。

我很满意 beanshell 完成了将 java 类的字符串评估为实际 Class 对象的繁重工作。然而,beanshell 已经在 2.0b4 版本上运行了很长时间,它的局限性(没有构造函数,甚至没有默认值;没有泛型,没有 for-each,没有枚举......)很烦人。

提醒 - 这将用作调试接口,因此可以忽略性能考虑。但是,我不能让服务器重新启动,不能将类文件发送到该位置,并且 JSP 对我来说是一个非常糟糕的选择(我不会在这里讨论原因)。此外,最终产品必须是一个类(或该类的一个对象),以便我可以传递它。

一些限制:我没有 JDK,所以没有 javax.tools.JavaCompiler。我没有 JSP,因为我没有 tomcat 或其他“真正的”Web 容器。 Java 5 语法支持会很棒,尤其是泛型、枚举和参数化。对默认构造函数的支持会非常好。

有什么想法吗?

编辑 1:我刚刚发现有一种在 beanshell 中有构造函数的迂回方式 - 但是你必须将它们声明为“public void XXX(){...}”而不是通常的方式“public XXX (){...}"。

【问题讨论】:

    标签: java compilation in-memory evaluate


    【解决方案1】:

    如果您由于许可原因无法捆绑 SUN JDK tools.jar,也许您可​​以包含 Eclipse JDT Core 编译器,请参阅

    http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_api_compile.htm

    这是例如Jetty Web 服务器的 JSP 实现是做什么的。

    【讨论】:

    • 嗯,我做到了。这将要求我:1. 直接依赖于 JDT,这对我(组织级别)来说是个问题,或者 2. 依赖于不保证不会改变的码头内部结构。还是谢谢
    【解决方案2】:

    您不能直接复制到 tools.jar 并获取 javax.tools.JavaCompiler 并将其添加到类路径中吗?还是许可问题。

    此代码和类路径中的 tools.jar 似乎可以正常工作:

    import java.io.File;
    import java.io.IOException;
    import java.util.Arrays;
    import javax.tools.JavaCompiler;
    import javax.tools.JavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    
    
    public class Main
    {
        public static void main(final String[] argv)
            throws IOException
        {
            final File[]                             files;
            final JavaCompiler                       compiler;
            final StandardJavaFileManager            fileManager;
            final Iterable<? extends JavaFileObject> compilationUnits;
    
            files = new File[]
            {
                new File(argv[0]),
            };        
            compiler         = ToolProvider.getSystemJavaCompiler();
            fileManager      = compiler.getStandardFileManager(null, null, null);
            compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files));
    
            compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
            fileManager.close();
        }
    }
    

    【讨论】:

    • 没有。许可问题。此外,客户端可以更改我的服务器运行的 JRE,所以这也是一个兼容性问题。
    【解决方案3】:

    我记得很久以前读过有关字节码工程库 (BCEL) 的文章,当时 Java 1.4 风靡一时。见http://jakarta.apache.org/bcel/index.html。我从未使用过它,所以我只提及它,因为它似乎与您所询问的内容很接近(并且它适用于或至少适用于较旧的虚拟机)而且我还没有看到有人提及它。

    【讨论】:

    • 会调查的。虽然听起来不是一个有效的解决方案 - 开销太大。
    【解决方案4】:

    为什么它必须是生成类/对象的 Java 字符串是否有特定的原因?我的自发反应是 JRuby 正是您所寻找的——它似乎是一个非常稳固的平台,并且 Ruby 具有元编程的强大传统。

    【讨论】:

    • 必须是 Java 字符串,因为这里的所有开发人员都知道。我想编写一个“插件”,它将连接到正在运行的服务器并帮助调试它(生成日志消息、查询内部结构等)。强迫每个人都学习 ruby​​ 会使它在开始之前就过时(没有人会学习 - 没有人会使用它)。
    • 多么可悲——它会像手套一样适合你。正如您所注意到的,Java 通常不用于脚本是有原因的。我认为 Groovy 和 JavaScript(两者都比 Ruby 更接近 Java)也不可能?
    • @gustafc:是的,出于同样的原因。
    【解决方案5】:

    我最终使用了 Bean Shell。它并不完美,但它解决了 99% 的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-10
      • 2023-03-06
      • 1970-01-01
      • 2011-10-22
      • 2011-05-27
      • 2010-12-18
      • 2016-02-06
      相关资源
      最近更新 更多