【问题标题】:How to get the Groovy generated java source code如何获取 Groovy 生成的 java 源代码
【发布时间】:2013-11-19 16:33:05
【问题描述】:

我们有一些使用 Groovy 的遗留代码,我们想从应用程序中删除 Groovy,因此,我们需要获取使用 gmaven 插件后生成的 java 源代码。

基本上,换句话说,我正在动态生成新类(使用 gmaven Groovy maven 插件),我希望能够获得此类生成的类的 java 源代码。

我研究了一下,发现这个插件的唯一目标是

<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>

我看不到任何目标可以让您获得完全实现的 java 源代码,存根代码对我们来说是不够的,因为我们需要最终的实现源代码才能摆脱 Groovy。

【问题讨论】:

  • 我对Groovy不熟悉,但是Groovy的编译真的会生成一个中间Java源码吗?我对此表示怀疑。如果 Groovy 直接编译成字节码,那只能反编译字节码,转成对应的 Java 源码。无论如何,与其经历可能需要大量代码整理的过程,为什么不简单地使用 Java 重写它呢?
  • 为什么不把 Groovy 类重写成 Java 呢?如果你正在构建它,我假设你有源代码。这个问题在目前的形式下没有多大意义。你能详细说明一下吗?
  • 阿德里安,蒂姆感谢您的回答,阿德里安:谢谢阿德里安,也许您的权利。 Tim:这个问题至少对我来说是有意义的,因为我不想处理 Groovy :-)。我只是不想/没有时间完成那件事,groovy 代码是遗留的,所以我没有这样做,我只是想避免这样做。也许在创建 java 类之前将 groovy 源代码转换为 java 字节码,我只是想知道是否有一种快速简便的方法可以向 Groovy 询问生成的 java 源代码。如果 Groovy 编译不生成 java 源代码,那我就用反编译器。

标签: java groovy dynamically-generated gmaven-plugin


【解决方案1】:

我对 gmaven 插件不是很熟悉,但我认为它会将 groovy 代码编译成字节码。在这种情况下,您可以使用字节码反编译器,有一个很好的列表here。过去我使用过 JAD,它非常好。最好的也会尝试根据类名创建有意义的变量名。

虽然有一个警告 - Groovy 对象是从 GObject 派生的,而不是 java.lang.Object,因此您可能需要保留 groovy jar 直到 groovy->java 移植完成。另外,请做好准备,它不会是一个非常容易阅读的 java...

【讨论】:

  • 谢谢大卫!,我想到了反编译器,是的,但是对我来说,groovy 不允许你获取你的 java 源代码看起来很奇怪/很烦人......最好的问候!
【解决方案2】:

它可能超出了您的范围(1 岁),但我解决了同样的问题并找到了一种从反编译的 groovy 类中检索算法(不是 java 源代码)的方法。

你可能想看看:http://michael.laffargue.fr/blog/2013/11/02/decompiling-groovy-made-classes/

【讨论】:

    【解决方案3】:

    生成的存根对您毫无用处。它们正是它们的名字所暗示的:存根。

    存根仅在进行联合 java/groovy 编译时有用。那是因为在一个 java/groovy 混合项目中涉及到两个编译器。

    1. 常规解析
    2. 创建存根
    3. 编译 java 和存根(使用 javac)
    4. 继续 groovy 编译(使用 groovyc)

    groovy 代码将使用groovyc 编译器进行编译,结果为字节码。

    这是一个生成的存根示例:

    package maba.groovy;
    
    import java.lang.*;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import groovy.lang.*;
    import groovy.util.*;
    
    @groovy.util.logging.Log4j() public class Order
        extends java.lang.Object  implements
        groovy.lang.GroovyObject {
        public  groovy.lang.MetaClass getMetaClass() { return (groovy.lang.MetaClass)null;}
        public  void setMetaClass(groovy.lang.MetaClass mc) { }
        public  java.lang.Object invokeMethod(java.lang.String method, java.lang.Object arguments) { return null;}
        public  java.lang.Object getProperty(java.lang.String property) { return null;}
        public  void setProperty(java.lang.String property, java.lang.Object value) { }
        public  int getPrice() { return (int)0;}
        public  void setPrice(int value) { }
        public  int getQuantity() { return (int)0;}
        public  void setQuantity(int value) { }
        @java.lang.Override() public  java.lang.String toString() { return (java.lang.String)null;}
    }
    

    如您所见,没有任何用处。而且你仍然会依赖一些 groovy 库。

    【讨论】:

    • 嗨,maba,也许我的问题不清楚,很抱歉,但我可以获得存根,是的,我只是无法获得实现的 java 源文件,这就是问题所在。 :-)。谢谢回答 !干杯
    【解决方案4】:

    此问题已在一段时间前出现在邮件列表中 [0]。总结一下:从 Groovy 到 Java 很难实现,因为 Java 中不存在语言结构和 API(如果您确实想完全删除 Groovy 依赖项)。

    特别是在引入调用站点缓存和其他性能优化技术后,生成的 Java 代码看起来很像这样(为了简单起见,我只是将一些脚本放入 JD-GUI [1]):

    public class script1351632333660 extends Script
    {
    public script1351632333660()
    {
    script1351632333660 this;
    CallSite[] arrayOfCallSite = $getCallSiteArray();
    }
    
    public script1351632333660(Binding arg1)
    {
    Binding context;
    CallSite[] arrayOfCallSite = $getCallSiteArray();
    ScriptBytecodeAdapter.invokeMethodOnSuperN($get$$class$groovy$lang$Script(), this, "setBinding", new Object[] { context });
    }
    
    public Object run()
    {
    CallSite[] arrayOfCallSite = $getCallSiteArray(); Object items = ScriptBytecodeAdapter.createList(new Object[0]);
    Object[] item = (Object[])ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.createList(new Object[] { "Fluff", arrayOfCallSite[1].callConstructor($get$$class$java$util$Date()), (Integer)DefaultTypeTransformation.box(11235813) }), $get$array$$class$java$lang$Object());
    
    arrayOfCallSite[2].call(items, item);
    
    arrayOfCallSite[3].callCurrent(this, items);
    
    ValueRecorder localValueRecorder = new ValueRecorder();
    try
    {
    Object tmp102_101 = items; localValueRecorder.record(tmp102_101, 8);
    Object tmp126_121 = arrayOfCallSite[4].call(tmp102_101, new script1351632333660._run_closure1(this)); localValueRecorder.record(tmp126_121, 14); if (DefaultTypeTransformation.booleanUnbox(tmp126_121)) localValueRecorder.clear(); else ScriptBytecodeAdapter.assertFailed(AssertionRenderer.render("assert items.findAll { it }", localValueRecorder), null);  } finally {
    localValueRecorder.clear(); throw finally; } return null; return null; } 
    static { __$swapInit();
    Long localLong1 = (Long)DefaultTypeTransformation.box(0L);
    __timeStamp__239_neverHappen1351632333665 = localLong1.longValue();
    Long localLong2 = (Long)DefaultTypeTransformation.box(1351632333665L);
    __timeStamp = localLong2.longValue(); } 
    class _run_closure1 extends Closure implements GeneratedClosure { public _run_closure1(Object _thisObject) { super(_thisObject); } 
    public Object doCall(Object it) { CallSite[] arrayOfCallSite = $getCallSiteArray(); return it; return null;
    }
    
    // ...
    

    [0]http://groovy.329449.n5.nabble.com/Java-lt-gt-Groovy-converters-td337442.html

    [1]http://java.decompiler.free.fr

    【讨论】:

    • 安德烈,谢谢,它看起来很复杂......现在我明白为什么它只是从 groovy 到 java 字节码......将尝试通过反编译器得到一些东西......非常感谢你的准确的答案。最好的问候哈维尔
    猜你喜欢
    • 2011-09-09
    • 2021-07-21
    • 2017-12-17
    • 2011-04-02
    • 2011-02-25
    • 2013-06-23
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多