You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Groovy代码编译为.class文件本地存储时遇MissingPropertyException求助

问题描述

我最近在研究如何将Groovy代码编译为.class文件并保存到本地,但遇到了MissingPropertyException异常。

相关代码

import gewu.blue.model.DynamicActionContextFactory

def stringResult = "//\n" +
        "// Source code recreated from a .class file by IntelliJ IDEA\n" +
        "// (powered by FernFlower decompiler)\n" +
        "//\n" +
        "\n" +
        "package gewu.blue.action.system;\n" +
        "\n" +
        "import gewu.blue.exception.DataPermissionException;\n" +
        "import gewu.blue.kaovy.ActionContext;\n" +
        "import gewu.blue.model.ErrorInfo;\n" +
        "import gewu.blue.record.PermissionUtil;\n" +
        "import gewu.util.SpringUtil;\n" +
        "import groovy.lang.MetaClass;\n" +
        "import groovy.transform.Generated;\n" +
        "import java.util.List;\n" +
        "import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;\n" +
        "import org.codehaus.groovy.runtime.callsite.CallSite;\n" +
        "import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;\n" +
        "\n" +
        "public class ActionSaveData extends ActionContext {\n" +
        "    private PermissionUtil permissionUtil;\n" +
        "\n" +
        "    @Generated\n" +
        "    public ActionSaveData() {\n" +
        "        CallSite[] var1 = $getCallSiteArray();\n" +
        "        super();\n" +
        "        PermissionUtil var2 = (PermissionUtil)ScriptBytecodeAdapter.castToType(var1[0].call(SpringUtil.class, \"permissionUtil\"), PermissionUtil.class);\n" +
        "        this.permissionUtil = var2;\n" +
        "        MetaClass var3 = this.$getStaticMetaClass();\n" +
        "        this.metaClass = var3;\n" +
        "    }\n" +
        "\n" +
        "    public Object run(List args) {\n" +
        "        CallSite[] var2 = $getCallSiteArray();\n" +
        "        Object record = var2[1].call(args, 0);\n" +
        "        Object fields = var2[2].call(args, 1);\n" +
        "        Object hasPermissionBeforeSave = var2[3].call(this.permissionUtil, record);\n" +
        "        if (!DefaultTypeTransformation.booleanUnbox(hasPermissionBeforeSave)) {\n" +
        "            throw (Throwable)var2[4].callConstructor(DataPermissionException.class, var2[5].callGetProperty(ErrorInfo.class));\n" +
        "        } else {\n" +
        "            var2[6].call(record);\n" +
        "            var2[7].callStatic(ActionSaveData.class, ScriptBytecodeAdapter.createList(new Object[]{record}), ScriptBytecodeAdapter.createList(new Object[]{fields}));\n" +
        "            return record;\n" +
        "        }\n" +
        "    }\n" +
        "}\n"
def baseDir = "/Users/wangkaipeng/Desktop/groovy编译"
new File(baseDir,"demo2"+".class").withWriter('utf-8') { writer ->
    writer.writeLine(stringResult)
}

异常详情

异常信息:groovy.lang.MissingPropertyException: No such property: $getCallSiteArray for class: gewu.blue.action.system.ActionSaveData

问题分析与解决方案

你当前的做法完全错误——把反编译出来的Java代码(包含Groovy编译器生成的特殊符号$getCallSiteArray)直接写入.class文件,这不是编译,只是把文本当成字节码文件保存,必然报错。

正确的做法是编译Groovy源码,而非操作反编译后的Java代码:

  1. 编写真正的Groovy源码(示例ActionSaveData.groovy):
package gewu.blue.action.system

import gewu.blue.exception.DataPermissionException
import gewu.blue.kaovy.ActionContext
import gewu.blue.model.ErrorInfo
import gewu.blue.record.PermissionUtil
import gewu.util.SpringUtil

class ActionSaveData extends ActionContext {
    private PermissionUtil permissionUtil = SpringUtil.getBean("permissionUtil") as PermissionUtil

    Object run(List args) {
        def record = args[0]
        def fields = args[1]
        if (!permissionUtil.hasPermissionBeforeSave(record)) {
            throw new DataPermissionException(ErrorInfo.INSTANCE)
        }
        record.save()
        ActionSaveData.staticMethod([record], [fields])
        return record
    }
}
  1. 使用Groovy编译器编译源码
    • 方式一:通过Groovy CLI命令编译
    groovyc -d /Users/wangkaipeng/Desktop/groovy编译 ActionSaveData.groovy
    
    • 方式二:在Groovy代码中调用编译器API
    import org.codehaus.groovy.control.CompilerConfiguration
    import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
    import groovy.transform.Generated
    
    def baseDir = new File("/Users/wangkaipeng/Desktop/groovy编译")
    def sourceFile = new File(baseDir, "ActionSaveData.groovy")
    def compilerConfig = new CompilerConfiguration()
    compilerConfig.setTargetDirectory(baseDir)
    
    // 如需添加生成注解等自定义配置,可添加自定义器
    compilerConfig.addCompilationCustomizers(new ASTTransformationCustomizer(Generated))
    
    // 编译源码
    new GroovyClassLoader().compile(sourceFile, compilerConfig)
    

关键说明

  • $getCallSiteArray是Groovy编译器生成的内部方法,不会出现在手写的Groovy源码中,仅反编译class文件时可见。
  • 直接写入文本到.class文件无法生成有效的字节码,必须通过Groovy编译器处理源码生成正确的class文件。

内容的提问来源于stack exchange,提问作者CarpeWang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 03:35:18