问题标签 [groovyclassloader]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
444 浏览

groovy - 无法卸载 Groovy 类 - PermGen Erros

我有一个广泛使用Groovy1.0 版的旧系统,目前我无法更新Groovy到更新版本。PermGen由于所有Groovy类/脚本都保存在内存中,即使没有人再使用它们, 我有时也会遇到错误。

我试图弄清楚在我使用完这些类后卸载它们的正确方法是什么。

我正在使用以下代码来创建 Script 对象:

我正在尝试以下代码来卸载生成的类:

不幸的是,这似乎不起作用,因为我不断收到PermGen错误。我怎样才能卸载Groovy类并保持PermGen合理的大小?

0 投票
0 回答
1027 浏览

jenkins - 替换正在运行的 Groovy 脚本(Jenkins 流水线脚本)的类路径

在 Jenkins Pipeline 中,我们有一个由 CPSGroovyShell 执行的 CpsGroovyScript,它带有一个自定义类路径,该路径附加到全局库位置的路径。

为了能够在使我的 Jenkins 实例上的所有管道可用之前测试我的更改,我想通过卸载类并在运行时从自身修改脚本的类路径来覆盖类路径。

我的想法是在当前类路径之前添加一个新位置,以便首先找到更改的类。this.class.classLoader.addURL()很棒,但新路径到类路径的末尾。

.../src- 这是当前生产代码的根目录,默认情况下它在类路径中 .../branch-src- 这是我更改代码的根目录,我希望使用它而不是.../src

例如.../src/com/foo/Bar.groovy.../branch-src/com/foo/Bar.groovy当我打电话import com.foo.Barnew com.foo.Bar()

如果这根本行不通,是否还有其他技巧,即完全替换原始类路径,或替换整个类加载器,无论如何。

0 投票
1 回答
4188 浏览

memory-leaks - Java8 中的 GroovyShell:内存泄漏/重复的类 [提供 src 代码 + 负载测试]

我们遇到了由 GroovyShell/Groovy 脚本引起的内存泄漏(请参阅最后的 GroovyEvaluator 代码)。主要问题是(从 MAT 分析器复制粘贴):

由“<system class loader>”加载的类“java.beans.ThreadGroupContext”占用807,406,960(33.38%)字节。

和:

由“sun.misc.Launcher$AppClassLoader @ 0x7004e9c80”加载的“org.codehaus.groovy.reflection.ClassInfo$ClassInfoSet$Segment”的16个实例占用1,510,256,544(62.44%)字节

我们使用的是Groovy 2.3.11 和 Java8(准确地说是 1.8.0_25)
升级到Groovy 2.4.6并不能解决问题。只是提高内存使用 只是稍微 ,尤其是。非堆。
我们正在使用的 Java 参数:-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC

顺便说一句,我读过https://dzone.com/articles/groovyshell-and-memory-leaks。当不再需要时,我们确实将GroovyShell shell 设置为 null。使用GroovyShell().parse()可能会有所帮助,但这对我们来说并不是一个真正的选择——我们有 >10 个集合,每个集合包含 20-100 个脚本,并且可以随时更改它们(在运行时)。

设置MaxMetaspaceSize也应该有所帮助,但它并不能真正解决根本问题,也不能消除根本原因。所以我仍在努力确定它。


我建立负载测试来重新创建问题(请参阅最后的代码)。当我运行它时:

  • 堆大小、元空间大小和类数量不断增加
  • 几分钟后进行的堆转储大于 4GB

前 3 分钟的性能图表: 在此处输入图像描述

正如我已经提到的,我正在使用 MAT 来分析堆转储。因此,让我们检查 Dominator 树报告:

在此处输入图像描述

Hashmap 占用 > 30% 的堆。那么让我们进一步分析一下。让我们看看里面有什么。让我们检查哈希条目:

在此处输入图像描述

它报告了 38 830 个条目。包括 38 780 个键匹配“.包括与“ .class Script.

另一件事,“重复课程”报告:

在此处输入图像描述

我们有 400 个条目(因为负载测试定义了 400 个 G.scripts),全部用于“ScriptN”类。他们都持有对 groovyclassloader$innerloader 的引用

我发现报告了类似的错误:https : //issues.apache.org/jira/browse/GROOVY-7498(请参阅最后的评论和随附的屏幕截图)-通过将 Java 升级到 1.8u51 解决了他们的问题。不过,这对我们没有任何帮助。

我们的代码:

负载测试:

有什么想法吗?提前谢谢

0 投票
1 回答
203 浏览

java - Groovy - 是否可以加载二进制类?

我有一个使用多个 groovy 脚本的 Java 应用程序,这些脚本在编译后使用GroovyShell.parse(text)方法缓存在内存中。

是否可以只编译一次这些脚本并将二进制类保存在磁盘/数据库上?以下代码将二进制类存储在/tmp;

运行此代码后,我可以在目录中看到myScript1.class,但尝试使用上述代码在应用程序重新启动后加载类(因此无需重新编译)失败:myScript2.class/tmp/

从我的源代码看,除了方法之外,GroovyClassLoader我没有看到任何加载二进制类的defineClass(java.lang.String, byte[])方法,这在尝试加载类时会出现以下异常:

Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 2901213189 in class file myScript1

有没有其他方法可以直接加载已编译的 groovy 类?

0 投票
0 回答
152 浏览

java - 配置 GrovyClassLoader 以遵循 @CompileStatic 注释

我有一个自定义 Java 库,它实现了在 Groovy 中实现并通过配置文件提供的业务规则。我使用 GroovyClassLoader 编译业务规则并返回所需的类,如下所示:

我的配置文件中嵌入的业务规则在类级别使用@CompileStatic 注释进行了注释。

如何让我的 GroovyClassLoader 配置为进行静态编译?

我猜它涉及使用 CompilerConfiguration 创建 GroovyClassLoader(即 GroovyClassLoader(ClassLoader loader, CompilerConfiguration config),但我很难找到配置 CompilerConfiguration 来完成此操作的特定信息。

谁能提供一个关于如何配置 GroovyClassLoader 进行静态编译的示例?

谢谢!

0 投票
1 回答
140 浏览

java - 加载名称冲突的 groovy 类

GroovyScriptEngine在我的 Java 应用程序中使用从不同来源动态加载代码。假设我有两个文件夹sources_A\sources_B\.

在每个文件夹中,我都有希望在运行时任意实例化的 Groovy 包和类。

问题:其中一些类在两个文件夹中具有相同的(完整)名称。

所以当我运行时有一个歧义:

当然,我可以创建两个不同的引擎:

但是当从这两个不同的引擎实例化的两个对象必须相互交互时,我遇到了问题:

错误:文件 bar.groovy 中方法 foo 中第 ** 行的参数类型不匹配

(不用说没有类型不匹配:对象具有正确的类型但由于引擎不同而无法识别)

简而言之,您是否有解决方案:

  • 具有某种方式来消除使用哪个源文件夹的歧义的单引擎解决方案?
  • 双引擎解决方案以某种方式让来自两个不同引擎的对象一起工作?
0 投票
1 回答
702 浏览

java - 如何在隔离的类加载器中执行 groovy 脚本?

我正在尝试在隔离的类加载器中运行 groovy 脚本,以便它们不会在调用类的依赖项的上下文中执行。

独立的.groovypom.xml摘录

我尝试过的上述任何变化总是会导致

我已经将此追溯到groovy.util.GroovyScriptEngine#loadScriptByName脚本被解析为 a 的Class<T>位置,其中 T 是脚本本身的名称。

我的理论是,这是由于 groovy 通过反射从脚本中创建合成类的方式,调用类中运行的 groovy 运行时和独立类加载器中运行的 groovy 运行时之间的二进制不兼容造成的。

关于如何实现这一点的任何想法?

0 投票
2 回答
235 浏览

groovy - Groovy:从文件和内存泄漏中重新编译一个类

根据参考文档

GroovyClassLoader 保留了它创建的所有类的引用,因此很容易造成内存泄漏。特别是,如果您执行两次相同的脚本,如果它是一个字符串,那么您将获得两个不同的类!

我使用文件作为解析源,但关闭了缓存:

日志输出总是

class MyClass <=> class MyClass 等于:false

如果我注释该行src.cachable = false,则类实例变得相等,但即使基础文件已更改,它们也不会重新编译。

因此问题是:我怎样才能正确地重新编译类而不造成内存泄漏?

0 投票
1 回答
2800 浏览

java - 使用 groovy 脚本引擎(GroovyClassLoader)运行包含新行“\n”的 Java 代码时出现 GroovyCastException

目前我正在研究一种以字符串形式运行java代码的方法。所以这就是我的做法。

问题是它在以下情况下失败。

我不明白为什么它会失败以及此错误消息的含义-

取消注释此代码后//sb.append(codeSnippet.replaceAll("\n", " "));,它可以工作。但请提出更好的处理方法。还有为什么它在解析类时不出错?我还能期待这样的其他惊喜吗?

0 投票
1 回答
351 浏览

java - Groovy 类无法在同一个包中找到超类

我在一个多模块项目的同一个包 ( ) 中有几个类。com.company.config

所有这些都用于继承一个java接口 ( MyInterface),但需要进行一些重构,所以我创建了一个groovy抽象类,它与其他脚本位于同一个包中;它实现MyInterface并由其他脚本继承。

自从这个改变以来,我似乎不能再从java代码中执行脚本了。

特别是,GroovyClassLoader::parseClass(File)抛出:

在第 7 行,确实可以找到导入声明

在第一次抛出相同的错误之后以及在我阅读了这个之后,我添加了它(尽管类在同一个包中) 。

在代码的以下Exception行中触发java

而我用以下参数调用这个函数

如前所述,在引入抽象类之前,一切正常。

groovy为什么即使有导入声明,类也不能在同一个包中找到它的超类?


这是内部调用的堆栈跟踪:

其余的堆栈跟踪是相对于应用程序调用的,所以它没有帮助。


编辑我

我确实注意到他们对其他类以及它们所在的位置GroovyClassLoader一无所知,所以我只是添加了groovy"./modules/module-setup/src/com/company/config/"

但我得到的结果和以前一样。

该路径肯定是正确的,因为File实例是用它创建的,并且可以由类加载器打开。