问题标签 [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.
groovy - 无法卸载 Groovy 类 - PermGen Erros
我有一个广泛使用Groovy
1.0 版的旧系统,目前我无法更新Groovy
到更新版本。PermGen
由于所有Groovy
类/脚本都保存在内存中,即使没有人再使用它们, 我有时也会遇到错误。
我试图弄清楚在我使用完这些类后卸载它们的正确方法是什么。
我正在使用以下代码来创建 Script 对象:
我正在尝试以下代码来卸载生成的类:
不幸的是,这似乎不起作用,因为我不断收到PermGen
错误。我怎样才能卸载Groovy
类并保持PermGen
合理的大小?
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.Bar
或new com.foo.Bar()
如果这根本行不通,是否还有其他技巧,即完全替换原始类路径,或替换整个类加载器,无论如何。
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
正如我已经提到的,我正在使用 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 解决了他们的问题。不过,这对我们没有任何帮助。
我们的代码:
负载测试:
有什么想法吗?提前谢谢
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 类?
java - 配置 GrovyClassLoader 以遵循 @CompileStatic 注释
我有一个自定义 Java 库,它实现了在 Groovy 中实现并通过配置文件提供的业务规则。我使用 GroovyClassLoader 编译业务规则并返回所需的类,如下所示:
我的配置文件中嵌入的业务规则在类级别使用@CompileStatic 注释进行了注释。
如何让我的 GroovyClassLoader 配置为进行静态编译?
我猜它涉及使用 CompilerConfiguration 创建 GroovyClassLoader(即 GroovyClassLoader(ClassLoader loader, CompilerConfiguration config),但我很难找到配置 CompilerConfiguration 来完成此操作的特定信息。
谁能提供一个关于如何配置 GroovyClassLoader 进行静态编译的示例?
谢谢!
java - 加载名称冲突的 groovy 类
我GroovyScriptEngine
在我的 Java 应用程序中使用从不同来源动态加载代码。假设我有两个文件夹sources_A\
和sources_B\
.
在每个文件夹中,我都有希望在运行时任意实例化的 Groovy 包和类。
问题:其中一些类在两个文件夹中具有相同的(完整)名称。
所以当我运行时有一个歧义:
当然,我可以创建两个不同的引擎:
但是当从这两个不同的引擎实例化的两个对象必须相互交互时,我遇到了问题:
错误:文件 bar.groovy 中方法 foo 中第 ** 行的参数类型不匹配
(不用说没有类型不匹配:对象具有正确的类型但由于引擎不同而无法识别)
简而言之,您是否有解决方案:
- 具有某种方式来消除使用哪个源文件夹的歧义的单引擎解决方案?
- 双引擎解决方案以某种方式让来自两个不同引擎的对象一起工作?
java - 如何在隔离的类加载器中执行 groovy 脚本?
我正在尝试在隔离的类加载器中运行 groovy 脚本,以便它们不会在调用类的依赖项的上下文中执行。
独立的.groovy:pom.xml
摘录:
我尝试过的上述任何变化总是会导致
我已经将此追溯到groovy.util.GroovyScriptEngine#loadScriptByName
脚本被解析为 a 的Class<T>
位置,其中 T 是脚本本身的名称。
我的理论是,这是由于 groovy 通过反射从脚本中创建合成类的方式,调用类中运行的 groovy 运行时和独立类加载器中运行的 groovy 运行时之间的二进制不兼容造成的。
关于如何实现这一点的任何想法?
groovy - Groovy:从文件和内存泄漏中重新编译一个类
根据参考文档:
GroovyClassLoader 保留了它创建的所有类的引用,因此很容易造成内存泄漏。特别是,如果您执行两次相同的脚本,如果它是一个字符串,那么您将获得两个不同的类!
我使用文件作为解析源,但关闭了缓存:
日志输出总是
class MyClass <=> class MyClass 等于:false
如果我注释该行src.cachable = false
,则类实例变得相等,但即使基础文件已更改,它们也不会重新编译。
因此问题是:我怎样才能正确地重新编译类而不造成内存泄漏?
java - 使用 groovy 脚本引擎(GroovyClassLoader)运行包含新行“\n”的 Java 代码时出现 GroovyCastException
目前我正在研究一种以字符串形式运行java代码的方法。所以这就是我的做法。
问题是它在以下情况下失败。
我不明白为什么它会失败以及此错误消息的含义-
取消注释此代码后//sb.append(codeSnippet.replaceAll("\n", " "));
,它可以工作。但请提出更好的处理方法。还有为什么它在解析类时不出错?我还能期待这样的其他惊喜吗?
java - Groovy 类无法在同一个包中找到超类
我在一个多模块java-8项目的同一个包 ( ) 中有几个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
实例是用它创建的,并且可以由类加载器打开。