[Seasar-user:21926] (Seasar2.4)ClassLoaderのduplicate class definitionエラーが発生するケースがあります

今田 昇 [E-MAIL ADDRESS DELETED]
2014年 7月 17日 (木) 19:28:29 JST


お世話になっております。
今田と申します。

Seasar2を便利に利用させていただいております。
いつもありがとうございます。

さて、
Seasar2.4において
(試したのは2.4.46)
ClassLoaderのduplicate class definitionエラーが発生するケースがあります。

発生条件は以下のとおりです。

コンポーネント
例:root.service.sample.Test2Service.java
に、
以下のようなpublicメソッドを定義します。

package root.service.sample;

public class Test2Service {

        //0
        public void testA1() {
        }
        //1
        public void testB1() {
        }
        //2
        public void testC1() {
        }
        //3
        public void testD1() {
        }
        //4
        public void testE1() {
        }
        //5
        public void testF1() {
        }
        //6
        public void testG1() {
        }
        //7
        public void testH1() {
        }
        //8
        public void testI1() {
        }
        //9
        public void testJ1() {
        }

        //10
        public void testA() {
        }

}

そして、
customizer.diconに、
  <component name="serviceCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">
    <initMethod name="addCustomizer">
      <arg>traceCustomizer</arg>
    </initMethod>
  </component>

のように、
コンポーネントのメソッドに対してAOPを設定して、
スマートデプロイすると、

各メソッドに対して割り当てられるAOPのクラス名は、

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testA10

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testB11

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testC12

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testD13

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testE14

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testF15

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testG16

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testH17

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testI18

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testJ19

root.service.sample.Test2Service$$EnhancedByS2AOP$$149b290$$MethodInvocation$$testA10

のようになるので、

testA1 + 0
と
testA + 10

の部分でクラス名が重複してしまうのです。

メソッドが処理される順番は、
org.seasar.framework.aop.proxy.AopProxy.javaの
setupAspectsメソッドにて、

targetClass.getMethods()

にて取得される順番となります。

java.lang.ClassのgetMethods()メソッドは、
Method[]の配列が返されますが、
メソッドの順序はなんら保証されないため、
必ずしも、上記の順番にはならないのですが、
上記の順番にたまたまなってしまった場合には、
クラス名が重複して、
ClassLoaderの
duplicate class definitionエラーが発生してしまいます。

クラス名に連番を振っているのは、
同一メソッド名でのオーバーロードがあった場合の処置だと思いますが、
上記のケースがあるので、

最後のメソッド名 + 連番
の部分を
メソッド名 + “$$” + 連番
のようにする必要があると思います。
($$じゃなくても良いですが・・・)

具体的には、
org.seasar.framework.aop.javassist.AspectWeaver.java
の
getMethodInvocationClassNameメソッドを

return enhancedClassName + SUFFIX_METHOD_INVOCATION_CLASS
    + method.getName() + "$$" + methodInvocationClassList.size();

のように変更することで、エラーを回避できました。

対応方法に誤り、勘違い等があればご指摘ください。

以上、ご報告いたします。

-------------- next part --------------
HTMLの添付ファイルを保管しました...
URL: <http://ml.seasar.org/archives/seasar-user/attachments/20140717/e37c532a/attachment.html>


Seasar-user メーリングリストの案内