[英]JRuby PermGen. Out of memory. Heap space memory leaks
We are working on a big project. 我们正在做一个大项目。 During our development we faced with a big a problem related to Heap and PermGen Space.
在我们的开发过程中,我们遇到了一个与堆和PermGen空间有关的大问题。 Here our error message: Current error: java.lang.OutOfMemoryError: PermGen space.
这是我们的错误消息:当前错误:java.lang.OutOfMemoryError:PermGen空间。
System.out.println("Initialazing..");
//Spring applicaton context
WebApplicationContext wac = (WebApplicationContext) AppContext.getApplicationContext();
// prepare path to internal ruby
String scriptsPath = wac.getServletContext().getRealPath(RUBY_PATH);
String jrubyHome = wac.getServletContext().getRealPath("WEB-INF" + File.separator + "jruby");
// Initializing Scripting container
ScriptingContainer container = new ScriptingContainer(isShared ? LocalContextScope.SINGLETHREAD
: LocalContextScope.THREADSAFE, LocalVariableBehavior.PERSISTENT);
// Configuring scriptingcontainer to avoid memory leaks
container.setCompileMode(RubyInstanceConfig.CompileMode.OFF);
System.setProperty("org.jruby.embed.compilemode", "OFF");
System.setProperty("jruby.compile.mode", "OFF");
// Setup ruby version
container.setCompatVersion(CompatVersion.RUBY1_9);
// Set jruby home
container.getProvider().getRubyInstanceConfig().setJRubyHome(jrubyHome);
List<String> loadPaths = new ArrayList<String>();
// load path
loadPaths.add(scriptsPath);
container.getProvider().setLoadPaths(loadPaths);
// ruby dispatcher initializing and run in simple mood
String fileName = scriptsPath + File.separator + "dispatcher_fake.rb";
// run scriplet
container.runScriptlet(PathType.ABSOLUTE, fileName);
// terminate container to cleanup memory without any effects
container.terminate();
container=null;
… …
Description: above code create and configure Scripting container. 说明:上面的代码创建和配置脚本容器。 This methods running in separate thread.
此方法在单独的线程中运行。 We use 4 threads of ruby runs.
我们使用4条红宝石线。 If we use the same scripting container and call internal scriptlets (call internall methods in java threading) we get issues with ruby variables because it is visible cross threading.
如果我们使用相同的脚本容器并调用内部scriptlet(在Java线程中调用internall方法),则会遇到ruby变量的问题,因为它是可见的交叉线程。
Main issue with JRuby are: growing heap memory space and perm gen memory space. JRuby的主要问题是:增大堆内存空间和perm gen内存空间。 We can't call any system's garbage collection in the ruby code.
我们无法在ruby代码中调用任何系统的垃圾回收。
Bellow you can found simple parts of our scriptlet: Ruby: 在下面,您可以找到我们脚本的简单部分:Ruby:
ENV['GEM_PATH'] = File.expand_path('../../jruby/1.9', __FILE__)
ENV['GEM_HOME'] = File.expand_path('../../jruby/1.9', __FILE__)
ENV['BUNDLE_BIN_PATH'] = File.expand_path('../../jruby/1.9/gems/bundler-1.0.18/bin/bundle', __FILE__)
require 'java'
require 'rubygems'
require "bundler/setup"
require 'yaml'
require 'mechanize'
require 'spreadsheet'
require 'json'
require 'rest-client'
require 'active_support/all'
require 'awesome_print'
require 'csv'
require 'builder'
require 'soap/wsdlDriver' rescue nil
ROOT_DIR = File.dirname(__FILE__)
require File.join(ROOT_DIR, "base", "xsi.rb")
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
module JavaListing
include_package "com.util.listing"
end
class A
include JavaListing
def run
1000.times do |index|
puts "iterating #{index}"
prop = JavaListing::Property.new
prop.proNo = 111
prop.remoteID = "1111"
prop.ownerID = "1111"
prop.advertiserID = "1111"
prop.title = "Atite"
prop.summary = "Asummury"
prop.description = "Adescription"
# prop.images << JavaListing::Image.new("111", "Acaption")
prop.lat = 12.23
prop.lng = 13.21
#prop.address = JavaListing::Address.new("Acity", "Acountry")
prop.location = "Alocation"
prop.policy = JavaListing::Policy.new("AcheckinAt", "AcheckoutAt")
prop.surfaceArea = "Asurfscearea"
prop.notes[index] = JavaListing::Note.new("Atitle", "Atext")
prop.order = "Aorder"
prop.map = JavaListing::Map.new(true, 14)
prop.units[index] = JavaListing::Unit.new("Aproptype", 2)
obj = Nokogiri::XML "<root><elements><element>Application Error #{index} </element></elements></root>"
end
end
end
A.new.run
The same perm gen with other kinds of scriptlets containers: 与其他种类的scriptlet容器相同的perm gen:
Create properties using JSR223
使用JSR223创建属性
ScripHelperBase.java ScripHelperBase.java
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
Reader reader = null;
String fileName = scriptsPath + File.separator + "dispatcher_java.rb";
try {
reader = new FileReader(fileName);
} catch (FileNotFoundException ex) {
Logger.getLogger(ScriptHelperBase.class.getName()).log(Level.SEVERE, null, ex);
}
engine.eval(reader);
Ways to solution 解决方法
List item 项目清单
Increase PermGen space PermGen space was increased to 4Gb. 增加PermGen空间PermGen空间已增加到4Gb。 Soon it became full too.
很快它也变得满满的。
Create properties using BSF
使用BSF创建属性
String fileName = scriptsPath + File.separator + "dispatcher_fake_ruby.rb";
String jrubyhome = "WEB-INF" + File.separator + "jruby";
BSFManager.registerScriptingEngine("jruby", "org.jruby.embed.bsf.JRubyEngine", new String[]{"rb"});
BSFManager manager = new BSFManager();
manager.setClassPath(jrubyhome);
try {
manager.exec("jruby", fileName, 0, 0, PathType.ABSOLUTE);
} catch (BSFException ex) {
Logger.getLogger(ScriptHelperBase.class.getName()).log(Level.SEVERE, null, ex);
}
Conclusion: This mean that just increasing available space isn't a solution of this hot problem. 结论:这意味着仅增加可用空间并不能解决此热点问题。
The method described above don't allow to clear needed memory to original state. 上述方法不允许将所需的内存清除为原始状态。 It means that every additional script running still increase filled PermGen space.
这意味着运行的每个其他脚本仍然会增加PermGen的填充空间。
Running system using CompileMode=OFF
使用CompileMode = OFF运行系统
container.setCompileMode(RubyInstanceConfig.CompileMode.OFF);
System.setProperty("org.jruby.embed.compilemode", "OFF");
System.setProperty("jruby.compile.mode", "OFF");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.