[Seasar-user:1688] S2.1系の OutOfMemoryError について
Sadanori ITO
sito_dev
2005年 3月 27日 (日) 21:56:42 JST
伊藤 (sito) です。
S2 の 2.2 系がリリースされて個人的には解決済みの問題なのですが,何らかの
理由で現在も 2.1 系を利用されている方のためにご報告しておきます。
2.1(CGLIB 版)から 2.2(Javassist 版)に変更されることになった理由である
パフォーマンスの問題と根本の原因は同じと思いますが,instance="prototype" を
指定したコンポーネントに aspect を適用した状態で,繰り返し取得し続けると
OutOfMemoryError が発生します。
※検証環境では 2000 回を超えた程度の呼び出し回数で発生。
検証するためのコードを書いただけで,それ以上深く追っていないため,推測に
しかならないのですが,こちらの日記 http://d.hatena.ne.jp/noryksj/20050220
で試されていたように
a. CGLIB が毎回生成される AopProxy.MyCallbackFilter を HashMap に蓄積してしまう
b. ClassLoader が毎回生成される Enhance 済みクラスをロードしたまま蓄積してしまう
のどちらか(あるいは両方)が引き起こしている問題だと思います。
ちなみに Enhance 済みクラスを1度しか作成しない現行版(2.2 系)では,
1000 万回取得してもメモリ使用量は 9MB 程度で安定していました。
現在もダウンロードサイトには旧安定版として(?)目立つ場所に並んでいる
ようなので,2.1 系は 2.1.14 でメンテ終了ということであれば,ユーザの方は
その辺りを認識しつつ運用する必要があるかと思います。
以上ご報告まで。
----- 長くなりますが,以下に検証コードと結果を示しておきます
----- Java コード (OutOfMemory.java) -----
package examples.dicon;
import java.util.Date;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;
public class OutOfMemory
{
private static final String PATH = "examples/dicon/OutOfMemory.dicon";
public static void main(String[] args)
{
S2Container container = S2ContainerFactory.create(PATH);
for (int i = 1; i <= 10000; i++)
{
Date date = (Date) container.getComponent(Date.class);
if (i % 1000 == 0)
{
System.out.println(
"count " + i + ", date = " + date + ", " + date.getClass());
}
}
}
}
----- Dicon ファイル (OutOfMemory.dicon) -----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components>
<component name="traceInterceptor"
class="org.seasar.framework.aop.interceptors.TraceInterceptor"/>
<component class="java.util.Date" instance="prototype">
<aspect pointcut="getTime">traceInterceptor</aspect>
</component>
</components>
----- 実行環境 -----
Windows XP + J2SDK 1.4.2_07
Linux + J2SDK 1.4.2_07
※結果はどちらも同じでした。
----- S2.2.4 を利用した場合の結果 -----
count 1000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 2000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 3000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 4000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 5000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 6000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 7000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 8000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 9000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
count 10000, date = Sun Mar 27 19:33:00 JST 2005, class $$java.util.Date$$EnhancedByS2AOP$$1edc073
----- S2.1.14 を利用した場合の結果 -----
count 1000, date = Sun Mar 27 19:34:38 JST 2005, class $java.util.Date$$EnhancerByCGLIB$$5a5b1b4c
count 2000, date = Sun Mar 27 19:35:12 JST 2005, class $java.util.Date$$EnhancerByCGLIB$$f75a0473
net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:236)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:368)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:280)
at org.seasar.framework.aop.proxy.AopProxy.create(AopProxy.java:112)
at org.seasar.framework.container.assembler.AbstractConstructorAssembler.assembleDefault(AbstractConstructorAssembler.java:36)
at org.seasar.framework.container.assembler.AutoConstructorAssembler.assemble(AutoConstructorAssembler.java:28)
at org.seasar.framework.container.deployer.PrototypeComponentDeployer.deploy(PrototypeComponentDeployer.java:22)
at org.seasar.framework.container.impl.ComponentDefImpl.getComponent(ComponentDefImpl.java:72)
at org.seasar.framework.container.impl.S2ContainerImpl.getComponent(S2ContainerImpl.java:83)
at examples.dicon.OutOfMemory.main(OutOfMemory.java:18)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:373)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:218)
... 9 more
Caused by: java.lang.OutOfMemoryError
※ OutOfMemoryError も問題ですが,速度もかなり...2.2 があって良かったです。
--
s.ito
__________________________________
Do You Yahoo!?
Upgrade Your Life
http://bb.yahoo.co.jp/
Seasar-user メーリングリストの案内