2012-06-22 102 views
0

我們正在開發一個大項目。在我們的開發過程中,我們遇到了與堆和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); 

解決方法

  1. 列表項

  2. 增加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"); 
+0

[JRuby PermGen在ruby代碼中甚至使用java對象時,空間不足](http://stackoverflow.com/questions/11157262/jruby-permgen-out-of-space-even-use-java-objects -in-ruby-code) – Mischa

回答

0

的JRuby您正在使用原生Java類創建Ruby的代理 - 它們在運行時,默認情況下JVM它們保存在內存永遠創建新類。

Here是解決方案。

+0

即使我們使用下一個調整選擇,JRuby ScriptingContainer的JVM也不會釋放內存: -Xms256m -Xmx1024m -Dsun.rmi.dgc.client.gcInterval = 3600000 -Dsun.rmi.dgc.server .gcInterval = 3600000 -XX:+ UseConcMarkSweepGC -XX:+ CMSPermGenSweepingEnabled -XX:+ CMSClassUnloadingEnabled -XX:MaxPermSize參數=128米 至於我,我們可以在運行時開始從目前的JVM新的JVM: HTTP://thilosdevblog.wordpress .COM/2010/02/20/starting_a_new_jvm_in_java / – Veniamin