FROSTM0URNE 2023-01-12 23:56 采纳率: 100%
浏览 38
已结题

javassist相关应用,为何会出现只修改了一项的情况

javassist 应用问题

RT 先上代码 这是调用轮子的代码(实际应用时候的代码) ↓

ClassEditor editor = new ClassEditor("ItemLoreOrigin", clazz);

editor
      .addNewMethod("isAlreadyRemake", "public boolean isAlreadyRemake(){return true;}");
      CtMethod ctMethod = editor.copyMethod(methodName,"getEquipments");

editor
      .addMethod(ctMethod)
      .overrideMethod("getValidItem",
         "{" + "" +  "if ($1 == null){" +   "return new java.util.ArrayList();" +  "}" +  "" +   "return getEquipments($1,$2);" +  "" + "}")
      .insertForMethod("getEquipments",
        "{" +"java.util.UUID uuid = $1.getUniqueId();" +
              "java.util.List itemStacks = com.frostmourne.itemloreoriginapi.ItemLoreOriginAPI.getAllSourceItems(uuid);" +
              "$_.addAll(itemStacks);" + "}"
 , true)
 .remakeFile();

这是轮子的相关实现代码


    /**
     *
     * 向类文件的方法中插入内容<br/>
     * @param methodName 方法名称
     * @param src 方法内容
     * @param after 插入位置是否在后
     *
     **/
    public ClassEditor insertForMethod(String methodName,String src,boolean after){
        if (this.ctClass.isFrozen()){
            this.ctClass.defrost();
        }
        try {
            CtMethod declaredMethod = this.ctClass.getDeclaredMethod(methodName);
            if (after){
                declaredMethod.insertAfter(src);
            }else{
                declaredMethod.insertBefore(src);
            }
        } catch (NotFoundException e) {
            System.out.println("未找到要插桩的方法 " + methodName);
            System.out.println("如果你想新增方法请使用 addNewMethod 方法");
            return this;
        } catch (CannotCompileException e) {
            System.out.println("编译错误,请检查编译内容");
            System.out.println(src);
            return this;
        }
        return this;
    }

    /**
     *
     * 重写类文件的方法<br/>
     * @param methodName 方法名称
     * @param src 方法内容
     *
     **/
    public ClassEditor overrideMethod(String methodName,String src){
        if (this.ctClass.isFrozen()){
            this.ctClass.defrost();
        }
        try {
            CtMethod declaredMethod = this.ctClass.getDeclaredMethod(methodName);
            declaredMethod.setBody(src);
        } catch (NotFoundException e) {
            System.out.println("未找到要覆写的方法 " + methodName);
            System.out.println("如果你想新增方法请使用 addNewMethod 方法");
            return this;
        } catch (CannotCompileException e) {
            System.out.println("编译错误,请检查编译内容");
            System.out.println(src);
            return this;
        }
        return this;
    }
    public CtMethod copyMethod(String originalMethod,String copiedMethodName){
        try {
            CtMethod ctMethod = this.ctClass.getDeclaredMethod(originalMethod);
            return CtNewMethod.copy(ctMethod,copiedMethodName,this.ctClass,null);
        } catch (NotFoundException | CannotCompileException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     *
     * 写入修改后的类文件并重新加载插件(热加载)<br/>
     * 推荐使用/stop关服后重载<br/>
     *
     **/
    public void remakeFile(){
        try {

            System.out.println("正在备份要修改的插件");


            String path = clazz.getProtectionDomain().getCodeSource().getLocation().getPath().substring(1);

            MXStarsEx.getFileManager().copyFileUsingStream(new File(path),new File(path + ".bak"));

            byte[] bytes = this.ctClass.toBytecode();
            String fileName = ctClass.getName().replace(".","/") + ".class";

            boolean unload = MXStarsEx.getPluginManager().unload(Bukkit.getConsoleSender(), plugin);
            if (unload){
                System.out.println("插件 " + plugin + " 已卸载");
            }else{
                System.out.println("插件 " + plugin + " 卸载失败");
            }

            MXStarsEx.getFileManager().replaceJarFile(path,bytes,fileName);

            Plugin plugin1 = Bukkit.getPluginManager().loadPlugin(new File(path));
            Bukkit.getPluginManager().enablePlugin(plugin1);


            System.out.println("警告: 使用热加载后的插件可能会存在一些隐患");
            System.out.println("警告: 推荐使用/stop重启服务器");

            ClassPool.getDefault().removeClassPath(new ClassClassPath(clazz));

        } catch (IOException | InvalidPluginException | InvalidDescriptionException e) {
            throw new RuntimeException(e);
        } catch (CannotCompileException e) {
            System.out.println("编译错误,请检查编译内容");
        }
    }

但是运行后却出现只能成功往同一个ClassEditor注入一项代码的情况
如getValidItem方法确实复制了一份并将其更名为getEquipments并将原方法的内容修改掉了
但是后面向getEquipments内插入内容的部分却被无视了
并未执行 反编译文件看之后发现getValidItems还是没有被按照代码正确修改
且addNewMethod方法一直是成功的

求问 这种情况是什么问题导致的 如何修复 万分感谢!

  • 写回答

1条回答 默认 最新

  • 流比 2023-01-15 12:51
    关注

    这个问题的原因很可能是你在调用轮子的代码中,调用了多次修改同一个方法的操作,导致只有最后一次操作生效。可以试着将调用轮子的代码中对同一个方法的多次修改合并成一次操作试试。

    另外,建议检查一下你使用的javassist版本是否与你项目中使用的java版本兼容,或者是否有其他依赖库冲突。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 1月25日
  • 已采纳回答 1月17日
  • 修改了问题 1月13日
  • 创建了问题 1月12日

悬赏问题

  • ¥15 (标签-UDP|关键词-client)
  • ¥15 关于库卡officelite无法与虚拟机通讯的问题
  • ¥15 qgcomp混合物线性模型分析的代码出现错误:Model aliasing occurred
  • ¥100 已有python代码,要求做成可执行程序,程序设计内容不多
  • ¥15 目标检测项目无法读取视频
  • ¥15 GEO datasets中基因芯片数据仅仅提供了normalized signal如何进行差异分析
  • ¥100 求采集电商背景音乐的方法
  • ¥15 数学建模竞赛求指导帮助
  • ¥15 STM32控制MAX7219问题求解答
  • ¥20 在本地部署CHATRWKV时遇到了AttributeError: 'str' object has no attribute 'requires_grad'