0

私たちは大きなプロジェクトに取り組んでいます。開発中に、ヒープとPermGenスペースに関連する大きな問題に直面しました。ここにエラーメッセージがあります:現在のエラー: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;

…</p>

説明:上記のコードは、スクリプトコンテナを作成および構成します。このメソッドは別のスレッドで実行されます。4スレッドのルビーランを使用します。同じスクリプトコンテナを使用して内部スクリプトレットを呼び出すと(Javaスレッドでinternallメソッドを呼び出す)、クロススレッドで表示されるため、ruby変数で問題が発生します。

JRubyの主な問題は、ヒープメモリスペースとpermgenメモリスペースの拡大です。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

他の種類のスクリプトレットコンテナと同じpermgen:

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に増加しました。すぐにそれもいっぱいになりました。

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スペースが増えることを意味します。

CompileMode=OFFを使用してシステムを実行している

container.setCompileMode(RubyInstanceConfig.CompileMode.OFF);
System.setProperty("org.jruby.embed.compilemode", "OFF");
System.setProperty("jruby.compile.mode", "OFF");
4

1 に答える 1

0

JRubyは、使用しているネイティブJavaクラス用のRubyプロキシを作成します。これらは実行時に作成される新しいクラスであり、デフォルトでは、JVMはそれらを永久にメモリに保持します。

これが解決策です。

于 2012-06-24T13:35:25.437 に答える