2017-04-27 7 views
0

初めてクラスが正常に作成されましたが、次回にクラスに変更があったとき(いくつかの変数を追加するなど)にエラーが発生します。 以下は私のコードです。既にロードされている実行時にJavaクラスを変更したい。これを行う方法?

ClassPool pool = ClassPool.getDefault(); 
     CtClass cc=null; 
     final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 
     if (contextClassLoader != null) 
     { 
      pool.insertClassPath(new LoaderClassPath(contextClassLoader)); 
     } 
     try{ 

      cc = pool.makeClass(className); 
      cc.defrost(); 
      for (Entry<String, Class<?>> entry : properties.entrySet()) { 
       cc.addField(new CtField(resolveCtClass(entry.getValue()), entry.getKey(), cc)); 
       // add getter 
       cc.addMethod(generateGetter(cc, entry.getKey(), entry.getValue())); 
       // add setter 
       cc.addMethod(generateSetter(cc, entry.getKey(), entry.getValue())); 

      } 
      cc.addConstructor(generateConstructor(cc,properties,className)); 
      CtConstructor defaultCons=new CtConstructor(NO_ARGS, cc); 
      defaultCons.setBody(";"); 
      cc.addConstructor(defaultCons); 
      return cc.toClass(); 
     }catch(Exception e){ 
      cc = pool.get(className); 
      cc.detach(); 
      cc = pool.makeClass(className); 
      cc.defrost(); 
      for (Entry<String, Class<?>> entry : properties.entrySet()) { 
       cc.addField(new CtField(resolveCtClass(entry.getValue()), entry.getKey(), cc)); 
       // add getter 
       cc.addMethod(generateGetter(cc, entry.getKey(), entry.getValue())); 
       // add setter 
       cc.addMethod(generateSetter(cc, entry.getKey(), entry.getValue())); 

      } 
      cc.addConstructor(generateConstructor(cc,properties,className)); 
      CtConstructor defaultCons=new CtConstructor(NO_ARGS, cc); 
      defaultCons.setBody(";"); 
      cc.addConstructor(defaultCons); 
      return **cc.toClass();** // getting error at this line 
     } 
+1

*この行にエラーが表示されます。*メッセージを教えてください。 – Jens

+0

javassist.CannotCompileException:java.lang.LinkageError:loader(org/jboss/modules/ModuleClassLoaderのインスタンス):名前の重複クラス定義を試みました –

+0

そのメッセージはちょっと私の答えにある説明に下線を引いています... – GhostCat

答えて

0

簡単な回答:(簡単に)できません。

ポイントは次のとおりです。クラスがで既にロードされている場合、の場合、JVMはすでにそのクラスに関する情報を持っています。 「デフォルト」のクラスローダーでは、単にという新しい定義でを置き換えることはできません。

あなたが動的に為替クラス定義したい場合は、そのようなことを可能にし、あなた自身のクラスローダを書くの高度なトピックに有効にする必要があります。開始点としてhereを参照してください。

+1

Javaassistはバイトコードを生成します。しかし、バイトコードはどのように実行時にクラスに変換されますか?そのバイトコードをロードしてクラスに変換するクラスローダー。 「バイトコードの存在の仕方」と「クラスのロード方法」には関係がありません。 – GhostCat

0

a Java agentと書いて、既に読み込まれたクラスを動的に変換する必要があります。 Javaエージェントは、agentmainという名前のメソッドを定義します。このメソッドは、2番目の引数としてInstrumentationのインスタンスをとります。ただし、このようなJavaエージェントを使用すると、適用できる変更はメソッドの本体を変更することに限定され、メンバ(フィールドまたはメソッド)を追加したり既存のシグネチャを変更することはできません。

Instrumentation::redefineClassを呼び出して再定義を適用します。

find articles on how to change loaded codeはオンラインの複数の場所にあります。

関連する問題