Groovy是一种动态语言,每个方法调用都是动态调度的。以优化Groovy中创建一个
metaClass为每个
java.lang.Class中
metaClassRegistry。这些
metaClass实例是按需创建的,并使用弱引用进行存储。
之所以看到很多,
org.prehaus.groovy.runtime.metaclass.metaMethodIndex.Entry是因为Groovy将类和方法的映射存储在内存中,以便可以在运行时快速调度它们。取决于应用程序的大小,这可能是因为您已经发现了数千个类,因为每个类可以具有数十个有时数百个方法。
但是,在Groovy和Grails中没有“内存泄漏”,您看到的是正常行为。您的应用程序内存不足,可能是因为尚未为其分配足够的内存,从而导致
metaClass实例被垃圾回收。现在假设您有一个循环:
for(str in strings) { println str.toUpperCase()}
在这种情况下,我们正在
String类上调用一个方法。如果内存不足,则将发生以下情况:对于循环的每次迭代,
metaClass将对其进行垃圾回收,然后再次为下一次迭代重新创建。如您所见,这会大大降低应用程序的运行速度,并导致CPU被固定。此状态通常称为“元类搅动”,是您的应用程序堆内存不足的标志。
如果Groovy中 没有 垃圾收集这些metaClass的情况下,那么是的,这将意味着有在Groovy内存泄漏,但事实证明 这是
垃圾收集这些类是一个迹象,一切都很好,只是,你还没有分配到足够的事实首先堆内存。这并不是说在应用程序的另一部分中可能存在内存泄漏,这正在耗尽所有可用的内存,并且不足以使Groovy正常运行。
至于您提到的其他答案, 除非 您在运行时动态解析类, 否则
添加类卸载和PermGen调整实际上不会解决内存问题。JVM使用PermGen空间存储动态创建的类。Groovy允许您在运行时使用
GroovyClassLoader.parseClass或编译类
GroovyShell.evaluate。如果您要连续解析类,那么可以添加类卸载标志会有所帮助。
但是,典型的Grails应用程序 不会 在运行时动态编译类,因此调整PermGen和类卸载设置实际上并不会实现任何目的。
您应该使用-Xmx标志验证是否分配了足够的堆内存,如果没有分配更多的堆内存,则应使用-Xmx标志。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)