2017-04-27 60 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:by java.lang.LinkageError:loader(org/jboss/modules/ModuleClassLoader的實例):嘗試重複名稱定義 –

+0

該消息有點強調了我在答案中給出的解釋... – GhostCat

回答

0

簡單的答案:你不能(容易)。

重點是:當類是已經加載那麼JVM已經有關於該類的信息。 「默認」類加載器根本不允許你用替換這個定義。

如果要動態交換類定義,你必須把編寫你自己的類加載器的高級主題,它允許這樣的事情。以here爲起點。

+1

Javaassist生成字節碼。但是,字節碼在運行時如何變成一個類?通過加載該字節碼的類加載器...並將它變成一個類。 「字節碼如何存在」與「如何加載類」之間沒有關係。 – GhostCat

0

您需要編寫a Java agent並動態添加它以在已經加載的類中轉換它。 Java代理定義了一個名爲agentmain的方法,該方法以Instrumentation的實例作爲其第二個參數。使用這樣的Java代理,您允許應用的更改僅限於更改方法的主體,您不能添加成員(字段或方法)或更改現有方法的簽名。

您致電Instrumentation::redefineClass來應用重新定義。

你可以在幾個地方在線上find articles on how to change loaded code

相關問題