首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我想在运行时更改已经加载的java类。该怎么做呢?

我想在运行时更改已经加载的java类。该怎么做呢?
EN

Stack Overflow用户
提问于 2017-04-27 17:09:21
回答 2查看 3.1K关注 0票数 1

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

代码语言:javascript
复制
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
        }
EN

回答 2

Stack Overflow用户

发布于 2017-05-02 04:34:04

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

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

你可以在几个地方在线find articles on how to change loaded code

票数 3
EN

Stack Overflow用户

发布于 2017-04-27 17:12:11

答案很简单:你不能(很容易)。

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

如果您想要动态地交换类定义,则必须转向高级主题,即编写允许这样做的自己的类加载器。请参阅here作为起点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43653397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档