我們正在開發一個大項目。在我們的開發過程中,我們遇到了與堆和PermGen空間有關的大問題。在這裏我們的錯誤消息:當前錯誤:java.lang.OutOfMemoryError:PermGen空間。JRuby 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;
...
說明:上面的代碼創建和配置腳本容器。這個方法在單獨的線程中運行。我們使用4線程的紅寶石運行。如果我們使用相同的腳本容器並調用內部scriptlet(在java線程中調用internall方法),我們會遇到ruby變量的問題,因爲它是可見的跨線程。
JRuby的主要問題是:增長的堆內存空間和perm gen內存空間。我們不能在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
同樣的燙髮根與其他種類的小腳本的容器:
Create properties using JSR223
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);
解決方法
列表項
增加PermGen的空間 PermGen的空間增加爲4GB。很快它變得充滿了。
Create properties using 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);
}
結論:這是不是意味着只是增加了可用空間是沒有這麼熱,問題的解決方案。
上述方法不允許將所需內存清除爲原始狀態。這意味着每個額外的腳本運行仍然增加填充PermGen空間。
Running system using CompileMode=OFF
container.setCompileMode(RubyInstanceConfig.CompileMode.OFF);
System.setProperty("org.jruby.embed.compilemode", "OFF");
System.setProperty("jruby.compile.mode", "OFF");
[JRuby PermGen在ruby代碼中甚至使用java對象時,空間不足](http://stackoverflow.com/questions/11157262/jruby-permgen-out-of-space-even-use-java-objects -in-ruby-code) – Mischa