即使代码未编译,GroovyClassLoader 对 parseClass 的调用也会成功

2024-01-14

我试图将 Groovy 脚本作为类动态加载,但即使脚本的代码未编译,也会创建类对象。

例如,我加载 Groovy 脚本的 Groovy 代码的简化版本如下:

GroovyCodeSource src = new GroovyCodeSource(
    "blah blah blah",
    "Foo.groovy",
    GroovyShell.DEFAULT_CODE_BASE
)
new GroovyClassLoader().parseClass(src, true)

显然,代码blah blah blah不是合法的 Groovy 脚本。然而,已经成功地为此动态代码创建了一个类对象。根据GroovyClassLoader 的 JavadocparseClass method http://docs.groovy-lang.org/latest/html/api/groovy/lang/GroovyClassLoader.html#parseClass(groovy.lang.GroovyCodeSource,boolean) a CompilationFailedException对于这样的情况应该抛出。

怎么可能仍然为损坏的代码创建该类,以及如何根据代码是否可以编译成功地从动态 Groovy 源代码创建一个类?我做了很多研究和实验,但没有效果。


这是因为 groovy 提供了对方法和属性的动态访问,就 Groovy 而言,代码blah blah blah, 已验证。实际上,您正在为脚本提供代码(没有类声明)。编译后,你会得到一个扩展的类groovy.lang.Script http://docs.groovy-lang.org/latest/html/api/groovy/lang/Script.html.

那么,让我继续您的代码并向您展示它如何有效......

GroovyCodeSource src = new GroovyCodeSource(
    'blah blah blah',
    "Foo.groovy",
    GroovyShell.DEFAULT_CODE_BASE
)
def c = new GroovyClassLoader().parseClass(src, true)
println c                     //class Foo
println c.getSuperclass()     //class groovy.lang.Script

def i = c.newInstance()
//i.run()                     //MissingPropertyException: No such property: blah for class: Foo
i.setBinding([
    blah: { x-> return [blah: "x.class =${x.getClass()}"] }
] as Binding)
i.run()                       //SUCCESS

I would also advise you to run groovyconsole, enter blah blah blah, press Ctrl+T, and check what class was generated for your script. Note that you could switch between different compilation/parsing phases. enter image description here


一个可能的解决方法是使用CompileStatic方法或类上的注释:

//compilation of this code will fail with message
//[Static type checking] - The variable [blah] is undeclared.
@groovy.transform.CompileStatic
def f(){
    blah blah blah
}
f()

你可以强迫GroovyClassLoader对整个脚本进行静态验证。

假设您希望脚本仅访问一些预定义的变量/方法,并且您希望在编译步骤而不是运行时检查这一点。

下面的例子展示了如何做到这一点,但它会失败blah blah blah编译期间的代码:

import org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder
import org.codehaus.groovy.control.CompilerConfiguration
import groovy.transform.CompileStatic

//your base Script class that declares only valid members
//for example `log`
abstract class MyScript extends groovy.lang.Script{
    PrintStream log
}

//create compiler config with base script class 
CompilerConfiguration cc = new CompilerConfiguration()
cc.setScriptBaseClass(MyScript.class.getName())
//make static compilation set for class loader
cc = CompilerCustomizationBuilder.withConfig(cc){ 
    ast(CompileStatic) 
}
//create classloader with compile config
GroovyClassLoader gcl = new GroovyClassLoader(this.getClass().getClassLoader(),cc)


GroovyCodeSource src = new GroovyCodeSource(
    "log.println 'hello world'",
    "Foo.groovy",
    GroovyShell.DEFAULT_CODE_BASE
)
def c = gcl.parseClass(src, true)  //this will fail for 'blah blah blah' source
def i = c.newInstance(log:System.out)
i.run()

附: Groovy 中还有其他可用的代码转换器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

即使代码未编译,GroovyClassLoader 对 parseClass 的调用也会成功 的相关文章

  • 不支持的字段:将瞬间格式化为日期 ISO 时的年份[重复]

    这个问题在这里已经有答案了 我正在尝试将 Instant 格式化为 ldap 日期 ISO8601 但在 f format Instant now 处失败 String input 20161012235959 0Z DateTimeFor
  • 了解 netty 通道缓冲区和水印

    我正在尝试了解网络缓冲区和水印 作为一个测试用例 我有一个 netty 服务器 它向客户端写入数据 客户端被阻止 基本上每次读取之间有 10 秒的睡眠时间 在正常 I O 下 如果接收方被阻塞 TCP 发送方将受到限制 由于流量控制 发送速
  • 如何准确判断 double 是否为整数? [复制]

    这个问题在这里已经有答案了 具体来说 在 Java 中 我如何确定double是一个整数 为了澄清 我想知道如何确定 double 实际上不包含任何分数或小数 我主要关心的是浮点数的性质 我想到的方法 以及我通过谷歌找到的方法 基本上遵循以
  • Apache Thrift Java-Javascript 通信

    我正在编写一个基于 Apache Thrift 的 Java 服务器 它将从 Javascript 客户端接收数据 我已经完成了 Java 服务器 但问题是我可以获得 Javascript 客户端的工作示例 我无法找到一个好的示例 构建文档
  • 获取Android库中的上下文

    我正在编写一个 Android 应用程序 它的一些功能封装在内部库中 但是 要使此功能发挥作用 库需要一个应用程序上下文的实例 为图书馆提供这种上下文的最佳方式是什么 我看到了一些选择 但没有一个有吸引力 Have my library c
  • Java Junit 测试 HTTP POST 请求

    我需要测试以下方法而不改变方法本身 该方法向服务器发出 POST 方法 但我需要制作一个独立于服务器的测试用例 在将其重定向到本地文件之前 我测试了类似的方法 但为此我将协议指定为文件 主机名指定为 localhost 端口指定为 1 我的
  • 使用 kryo 注册课程的策略

    我最近发现了 kryonet 库 它非常棒并且非常适合我的需求 然而 我遇到的一个问题是制定一种好的策略来注册所有可以转移的类 我知道我可以在每个对象中编写一个静态方法 该方法将返回它使用的所有类的列表 但我真的不想这样做 为了我自己的时间
  • 使用 Jena 查询维基数据

    目前 Wikidata 有一个 SPARQL 端点 https query wikidata org https query wikidata org 我想使用 Jena 3 0 1 查询此网站 我使用以下代码 但收到错误消息 端点返回的
  • Java 中如何验证字符串的格式是否正确

    我目前正在用 Java 编写一个验证方法来检查字符串是否是要更改为日期的几种不同格式之一 我希望它接受的格式如下 MM DD YY M DD YY MM D YY 和 M D YY 我正在测试第一种格式 每次它都告诉我它无效 即使我输入了有
  • 如何在 Eclipse 中获得完全限定的类名?

    有没有一种快速方法可以在 Eclipse 中单击 Java 类并获取其完全限定名称 或将其复制到剪贴板 2016年6月29日编辑 正如 Jeff 所指出的 您只需要执行以下第二步 1 Double click on the class na
  • Time.valueOf 方法返回错误值

    我使用 Time valueOf 方法将字符串 09 00 00 转换为 Time 对象 如下所示 Time valueOf LocalTime parse 09 00 00 当我调用 getTime 来显示我得到的值时 28800000
  • 如何在 spring-data 中强制使用 CrudRepository 进行预加载?

    我有一个实体 其中包含List就是这样lazy默认加载 interface MyEntityRepository extends CrudRepository
  • 从字节数组设置 img src

    我需要设置img src我在对象中拥有的字节数组的属性 img
  • Spring - 如何在不匹配列名的情况下使用 BeanPropertyRowMapper

    我正在开发一个应用程序 该应用程序已使用行映射器从纯 JDBC 转换为 Spring 模板 我遇到的问题是数据库中的列与属性名称不匹配 这阻止我使用BeanPropertyRowMapper容易地 我看到一些关于在查询中使用别名的帖子 这会
  • 如何使用eclipse调试JSP tomcat服务?

    我想使用 Eclipse IDE 调试器来调试单独运行的 JSP Struts Tomcat Hibernate 应用程序堆栈 如何设置 java JVM 和 eclipse 以便设置断点 监视变量值并查看当前正在执行的代码 我刚刚用谷歌搜
  • 检查按钮是否可用?如果没有,请等待 5 秒钟,然后再次检查?

    基本上我想看看此刻是否可以单击按钮 如果没有我想再试一次 所以我需要某种 goto 函数来返回到代码的前一行 尽管我怀疑我写得非常糟糕 但它本来可以做得更容易 try driver findElement By xpath button i
  • java Web应用程序中的日期转换

    String date1 13 03 2014 16 56 46 AEDT SimpleDateFormat sdf new SimpleDateFormat dd MM yyyy HH mm ss z sdf setTimeZone Ti
  • Java时区混乱

    我正在运行 Tomcat 应用程序 并且需要显示一些时间值 不幸的是 时间快到了 还有一个小时的休息时间 我调查了一下 发现我的默认时区被设置为 sun util calendar ZoneInfo id GMT 08 00 offset
  • com.sun.xml.ws.message.saaj.SAAJHeader 无法转换为 com.sun.xml.ws.security.opt.impl.outgoing.SecurityHeader

    我正在尝试访问第三方 Web 服务 该服务要求我创建一个传递时间信息 用户名和密码的安全标头 我在网上搜索了可行的示例 并尝试了多种方法 我正在尝试使用 Java 6 中内置的内容来做到这一点 我不确定我做错了什么 从 WSDL 生成 We
  • 如何在J2ME中获取数字的幂[重复]

    这个问题在这里已经有答案了 可能的重复 J2ME power double double 数学函数实现 https stackoverflow com questions 2076913 j2me powerdouble double ma

随机推荐

  • 使用文档字符串和“未实现”异常预填充 Eclipse 和 Pydev 中的新函数

    我正在使用 Eclipse 和 Pydev 编辑 Python 源代码 我想记录我的所有函数 并在函数尚未实现时引发 未实现 异常 例如当我输入 def foo bar1 bar2 输入时 我希望它自动完成 def foo bar1 bar
  • 在 Vim 中控制选项卡名称

    在 MacVim 中 选项卡的名称似乎设置为该选项卡中最近打开的缓冲区的名称 这会在使用拆分时造成混乱 如何将选项卡名称固定到选项卡中的左上角窗口 以下函数返回左上角窗口中加载的缓冲区的名称 function GuiTabLabel ret
  • 碰撞后立即停止刚体运动/旋转

    我希望我的球体从一个位置跳到另一个位置 但不希望它随后平移 我不知道该怎么做 这是我的代码 void Update if thrown Input touchCount gt 0 Input GetTouch 0 phase TouchPh
  • 加入一组具有超时的 python 进程

    我正在使用 python 的多处理库来创建多个进程 from multiprocessing import Process processes Process target function for function in FUNCTION
  • 使用变量与文字时远程查询速度很慢

    我到处寻找这种情况 但找不到解决方案除了动态 SQL 我不想使用它 这是我想要在服务器 2 上更新的表 Stuff Id UNIQUEIDENTIFIER stuffname NVARCHAR 64 我需要从服务器 1 更新它 所以我一直在
  • 使用 np.divide (以及其他浮点数)将 0 除以 0 时如何抑制错误消息?

    我的尝试 import numpy as np np seterr divide ignore a np array 4 3 0 0 b np array 1 0 0 np divide a b 我得到的输出 main 1 RuntimeW
  • 如何在张量流中并行加载数据?

    首先我先介绍一下我的申请背景 我的磁盘中有大约 500 000 个以 avi 文件形式保存的视频 我将使用它们作为训练样本 要使用它们 我们可以将它们同时加载到内存中 然后将每个批次输入模型进行试验 这是最简单的方法 然而我的记忆是NOT足
  • 调用未定义的方法 Illuminate\Database\Query\Builder::save()

    我试图在现有记录上调用 Eloquent 的 save 方法 但从 Illuminate 的查询生成器中收到错误 按照 Laravel 网站上的文档进行操作http laravel com docs eloquent insert upda
  • 使用 React Query 过滤从 API 获取的列表

    我正在使用 React Query 第一次 来管理对 API 的调用 我正在获取发票列表 到目前为止我已经在下面的代码中成功完成了此操作 我现在想根据每个发票对象具有的状态属性 它是 已付款 待处理 或 草稿 使用一系列复选框来过滤此列表
  • Pharo Smalltalk 和 mySql

    我正在寻找知道如何连接 Pharo Smalltalk 和 mySql 的人 我只想做一些基本的事情 比如 从名称中选择 然后将结果读入 Pharo 有人对这个有了解吗 如果你有一个屏幕视频那就太好了 我会给你买杯啤酒 查看DBXTalk
  • Intellij IDEA中有没有类似Sublime的“HTML:编码特殊字符”的功能

    I m looking something like the functionality given in Sublime Text by the shortcut windows Ctrl Shift P named HTML Encod
  • 如何在类型提示中指定函数类型?

    如何将变量的类型提示指定为功能类型 没有typing Function 并且我在相关 PEP 中找不到任何内容 PEP 483 https www python org dev peps pep 0483 As jonrsharpe htt
  • 通过布尔掩码数组选择 numpy 数组的元素

    我有一个布尔掩码数组a长度n a np array True True True False False 我有一个二维数组n列 b np array 1 2 3 4 5 1 2 3 4 5 例如 我想要一个仅包含 True 值的新数组 c
  • C#进程启动焦点问题

    当我开始一个新进程时 它会自动获得焦点 如何防止它获得焦点或将焦点返回到我的应用程序 这是我正在使用的代码 string path c temp myprocess exe ProcessStartInfo info new Process
  • React、Jest 和 Material-UI:如何测试在模式或弹出窗口中呈现的内容

    有一些 Material ui 组件不会将其结果渲染到与其父组件放置的位置相同的位置 其中我们有Dialog Menu etc 这显然使得在安装了某些父组件的 jest js 包装器中测试其内容是否存在是不可能的 例如给定以下组件 clas
  • 如何动态设置膨胀线性布局中的边距?

    我添加了一个linearlayout in a linearlayout动态地使用此代码 LinearLayout root LinearLayout findViewById R id root View child inflater i
  • 停止页面加载时自动运行 ASP 脚本

    我这里遇到问题了 我创建了一个用于将记录添加到数据库中的页面 它工作正常 但是每次加载页面时都会运行 asp 脚本 每次加载页面时都会向数据库输入一条空白记录 这非常烦人 因为它与我有其他脚本 我觉得我很愚蠢 但我所需要的只是让脚本仅在单击
  • php 是否在“html body”之前加载?

    很难解释这个问题 但我目前正在将 php 页面中的变量传递给一些 html 隐藏输入 我使用 JavaScript 函数从隐藏输入中获取这些值 该函数的调用方式如下 它现在可以在我的系统上运行 但是从 php 传递的值是否有可能无法通过 因
  • 忽略第一维的二维 JavaScript 数组问题

    简而言之 我根据当前月份和日期填充一个数组 我不会在这里复制代码来获取当前月份和日期 因为它工作正常 它适当地返回变量 月 和 日 我的数组列表包含一年中每一天的项目 该数组以 开始 new var content 然后数组是这样列出的 删
  • 即使代码未编译,GroovyClassLoader 对 parseClass 的调用也会成功

    我试图将 Groovy 脚本作为类动态加载 但即使脚本的代码未编译 也会创建类对象 例如 我加载 Groovy 脚本的 Groovy 代码的简化版本如下 GroovyCodeSource src new GroovyCodeSource b