- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在加载大量 Groovy (2.4.6) 脚本并使用 GroovyScriptEngineImpl 运行它们在我的 Java 8 应用程序中,一段时间后我遇到了问题。
有几件事你需要知道:
GroovyScriptEngineImpl
每次我运行一个脚本GroovyClassLoader
每次我运行一个脚本我需要这样做,以便将每个脚本隔离在一个单独的“环境”中:我正在为某些脚本在类加载器中加载一些外部 JAR,我不希望其他脚本能够使用执行时这些 JAR 中的类。
我的问题来自这样一个事实,即对于我运行的每个脚本,GroovyClassLoader
将创建一个新的 ScriptXXXX
类并加载它,但永远不要卸载它。
这导致加载的类数量无限增加,内存最终被完全填满。
我尝试了很多不同的解决方案,但似乎都没有用:
-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC
在 JVM 参数中-Dgroovy.use.classvalue=true
在 JVM 参数中ScriptXXXX
创建的“元类”类如下所示:Groovy Classes not being collected but not signs of memory leak GroovyClassLoader
GroovyScriptEngineImpl
这是 ScriptXXXX
之一的“到 GC 的最短路径” Eclipse 内存分析器中的类:
我显然已经用完了这里的解决方案,而且似乎没有一个真正有效,因为类加载器总是保留对永远不会被 GC 处理的类的引用。
如果你想重现这个问题,这里有一个代码示例:
GroovyScriptEngineImpl se;
while (true)
{
se = new GroovyScriptEngineImpl(new GroovyClassLoader());
CompiledScript script = se.compile("println(\"hello\")");
script.eval(se.createBindings());
}
谢谢
更新 : 看完pczeus的回复后,我尝试限制元空间,有些类似乎确实在卸载,我认为这是ScriptXXX
类。
就是说,几分钟后我得到了 Out of Metaspace
脚本执行期间出错。
这是我使用 VisualVM 获得的配置文件:
以及 ScriptXXX
的 Eclipse 内存分析器中的“GC 路径”类确实是空的(它们不再是类的实例),即使该类仍列在直方图中。
最佳答案
这显然是一种边缘情况,需要特殊调整并可能选择所使用的垃圾收集方案。
由于您使用的是 Java8,并且您知道您正在加载数以千计的临时类,因此您应该尝试调整和限制可用的 MetaSpace
数量,并调整清理频率。直接来自https://blogs.oracle.com/poonam/entry/about_g1_garbage_collector_permanent :
JDK8: Metaspace
In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace. There are some new flags added for Metaspace in JDK 8:
-XX:MetaspaceSize= where is the initial amount of space(the initial high-water-mark) allocated for class metadata (in bytes) that may induce a garbage collection to unload classes. The amount is approximate. After the high-water-mark is first reached, the next high-water-mark is managed by the garbage collector
-XX:MaxMetaspaceSize= where is the maximum amount of space to be allocated for class metadata (in bytes). This flag can be used to limit the amount of space allocated for class metadata. This value is approximate. By default there is no limit set. -XX:MinMetaspaceFreeRatio= where is the minimum percentage of class metadata capacity free after a GC to avoid an increase in the amount of space (high-water-mark) allocated for class metadata that will induce a garbage collection.
-XX:MaxMetaspaceFreeRatio= where is the maximum percentage of class metadata capacity free after a GC to avoid a reduction in the amount of space (high-water-mark) allocated for class metadata that will induce a garbage collection.
By default class metadata allocation is only limited by the amount of available native memory. We can use the new option MaxMetaspaceSize to limit the amount of native memory used for the class metadata. It is analogous to MaxPermSize. A garbage collection is induced to collect the dead classloaders and classes when the class metadata usage reaches MetaspaceSize (12Mbytes on the 32bit client VM and 16Mbytes on the 32bit server VM with larger sizes on the 64bit VMs). Set MetaspaceSize to a higher value to delay the induced garbage collections. After an induced garbage collection, the class metadata usage needed to induce the next garbage collection may be increased.
关于Java/Groovy - GroovyClassLoader 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37301117/
我在 Java 类中使用 GroovyClassLoader 来解析某个(理想情况下是复杂的)groovy 文件(将在下一步中执行): 调用 MyClass.java final Class pars
我正在构建一个Grails应用程序,该应用程序允许用户编写Groovy代码,然后在我的框架内执行该代码。当然,这是一个巨大的安全威胁,因为用户可能输入恶意代码。 Groovy类正在使用GroovyCl
我有一个库,允许客户端提供文本文件列表,每个文件都包含用于扩展 java 类 Z 的类的 groovy 代码。例如文件“A.groovy”包含 package com.mypkg; public cl
我正在调查一些 JVM bsaed 代码(在 Java 环境中运行的 groovy)中的内存泄漏。 我有一个简单的 Java 测试类,用于调查 Groovy 类加载的各种行为,并且我正在运行以下代码(
我正在尝试使用 GroovyClassLoader 和 GroovyScriptEngineImpl 在我的 Java 应用程序中运行 Groovy 脚本,并且我想将 Groovy 脚本与父应用程序上
不幸的是,我们遇到了 PermgenError。 jmap -permstat 返回如下内容: 0x00000006c17f8520 1 1968 0x00000006ad000000
我正在加载大量 Groovy (2.4.6) 脚本并使用 GroovyScriptEngineImpl 运行它们在我的 Java 8 应用程序中,一段时间后我遇到了问题。 有几件事你需要知道: 我必须
我看到类似的代码 GroovyClassLoader cLoader = new GroovyClassLoader(this.class.getClassLoader()) 后面是这样的: cLoa
我正在尝试将 Groovy 脚本作为类动态加载,但即使脚本的代码未编译,也会创建类对象。 例如,我的用于加载 Groovy 脚本的 Groovy 代码的简化版本如下: GroovyCodeSource
我有一个 Java 7 项目,每 n 分钟由 n 个进程运行脚本。以下是运行脚本的代码示例。 ScheduledFuture scheduledFuture = scheduledService.sc
我需要从我的 Java 应用程序运行一些外部代码,这些代码将经常更新并与应用程序的其余部分正交。由于我不会为每次代码更改(以及其他原因)重新部署整个应用程序,我们选择使用 groovy对于此代码,并将
我注意到 scala 符合 jsr 223 https://issues.scala-lang.org/browse/SI-874 ...但是它能够做像 GroovyScriptEngine 这样的事
我在 java 中创建了一个自定义类,用于自定义加载 Groovy 类。 我的 Java 类是这样开始的: public class ClassLoader { private GroovyC
我正在尝试在java中使用GroovyClassLoader来执行Groovy类中的方法。 我创建了一个Java类,公共(public)方法创建了一个GroovyClassLoader的实例,pars
我正在尝试获取动态生成的groovy 脚本来继承类并实现调用java 程序的接口(interface)。我正在传递评估 groovy 脚本的类的类加载器,但没有效果。我想知道我是否可以询问一位 Gro
目前我正在研究一种以字符串形式运行java代码的方法。这就是我的做法。 import java.util.HashMap; import java.util.Map; import groovy.la
我有一个像这样的 groovy 脚本: @Grab('com.univocity:univocity-parsers:2.0.0') import com.univocity.parsers.csv.
我是一名优秀的程序员,十分优秀!