2017-04-27 221 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

相关问题