Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我想在运行时更改已经加载的java类。如何做到这一点?_Java_Javassist - Fatal编程技术网

我想在运行时更改已经加载的java类。如何做到这一点?

我想在运行时更改已经加载的java类。如何做到这一点?,java,javassist,Java,Javassist,第一次成功创建类,但下一次当类发生更改(如添加一些变量)时,它会抛出一个错误。 下面是我的代码 ClassPool pool = ClassPool.getDefault(); CtClass cc=null; final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null)

第一次成功创建类,但下一次当类发生更改(如添加一些变量)时,它会抛出一个错误。 下面是我的代码

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
        }
ClassPool=ClassPool.getDefault();
CTCC类=空;
final ClassLoader contextClassLoader=Thread.currentThread().getContextClassLoader();
if(contextClassLoader!=null)
{
insertClassPath(新LoaderClassPath(contextClassLoader));
}
试一试{
cc=pool.makeClass(类名);
cc.除霜();
对于(条目>条目:properties.entrySet()){
cc.addField(新的CtField(resolveCtClass(entry.getValue()),entry.getKey(),cc));
//添加吸气剂
cc.addMethod(generateGetter(cc,entry.getKey(),entry.getValue());
//添加设置器
cc.addMethod(generateSetter(cc,entry.getKey(),entry.getValue());
}
cc.addConstructor(generateConstructor(cc,properties,className));
CtConstructor defaultCons=新的CtConstructor(无参数,cc);
defaultCons.setBody(“;”);
cc.addConstructor(defaultCons);
return**cc.toClass();**//此行出错
}
简单的回答:你不能(轻松地)

关键是:当类已加载时,JVM就已经有了关于该类的信息。“默认”类加载器不允许用新定义替换该定义

如果您想动态地交换类定义,您必须转到高级主题,即编写您自己的类加载器,它允许这样做。将其视为起点

简单的回答:你不能(轻易地)

关键是:当类已加载时,JVM就已经有了关于该类的信息。“默认”类加载器不允许用新定义替换该定义

如果您想动态地交换类定义,您必须转到高级主题,即编写您自己的类加载器,它允许这样做。将其视为起点

您需要动态编写并附加它,以便在类已加载后对其进行转换。Java代理定义了一个名为
agentmain
的方法,该方法将
Instrumentation
的实例作为其第二个参数。使用这样的Java代理,允许应用的更改仅限于更改方法体,不能添加成员(字段或方法)或更改现有成员的签名

您可以调用
Instrumentation::redefineClass
来应用重新定义

您可以在线访问多个位置。

您需要动态编写并附加它,以便在类加载后对其进行转换。Java代理定义了一个名为
agentmain
的方法,该方法将
Instrumentation
的实例作为其第二个参数。使用这样的Java代理,允许应用的更改仅限于更改方法体,不能添加成员(字段或方法)或更改现有成员的签名

您可以调用
Instrumentation::redefineClass
来应用重新定义


您可以在多个地方在线查看。

在这一行出现错误,您能告诉我们消息吗?javassist.cannotcompileeException:by java.lang.LinkageError:loader(org/jboss/modules/ModuleClassLoader的实例):尝试为名称复制类定义该消息在我回答中给出的解释下面划线…在这一行出现错误您能告诉我们消息吗?javassist.CannotCompileException:by java.lang.LinkageError:loader(org/jboss/modules/ModuleClassLoader的实例):尝试为名称复制类定义该消息在我的回答中给出的解释下面划线…Javaassist生成字节码。但是字节码是如何在运行时变成类的呢?通过类加载器加载字节码。。。把它变成一门课。“字节码是如何产生的”和“类是如何加载的”之间没有关系。Javaassist生成字节码。但是字节码是如何在运行时变成类的?通过类加载器加载字节码…并将其变成类。在“字节码是如何产生的”和“类是如何加载的”之间没有关系。