从 rt.jar 重新加载带有操纵字节码的类



我目前正在尝试跟踪用于学习目的的方法调用。

我实现的javagent是本文中实现的修改版本。该程序将任何方法的调用记录指令添加到字节码中。不幸的是,引导类加载器拒绝从 rt.jar 加载任何纵的内容。我可以理解这对于生产环境来说不是一个好主意,但对于学生来说,这将是非常惊人的。

你有什么想法如何实现这一目标吗?

我可以成功地从 rt.jar 操作类。

例如,作了BigDecimal类的字节码。您正在训练哪个课程来操纵?你在做什么样的操纵?只是像您提到的文章中那样将日志添加到类的每个方法中?

除了遵循文章的说明之外,我还必须做一些其他事情才能操作 rt.jar 的类。

  1. LoggerAgent类中,我添加了一个我明确想要操作的类数组。

    String[] includeArr = new String[] { "java/math/BigDecimal" };
    ArrayList<String> include = new ArrayList(Arrays.asList(includeArr));
    
  2. LoggerAgent类的transform方法中,我修改了循环以包含我明确想要操作的类。

    for (int i = 0; i < ignore.length; i++) {
        if (className.startsWith(ignore[i]) && !include.contains(className)) {        
            return bytes;
        }
    }
    
  3. 修复了 JavassistHelper 的方法methodReturnsValue,以正确区分方法和构造函数。

    private static boolean methodReturnsValue(CtBehavior method)throws NotFoundException {
        if (method instanceof CtMethod){
            CtClass returnType = ((CtMethod) method).getReturnType();
            String returnTypeName = returnType.getName();
            if(returnTypeName.equals("void")){
                return false;
            }else{
                return true;
            }    
        } else{
            return false;
        }
    }
    
  4. 最后,在 HelloWorld 类中,我创建了一个BigDecimal来检查操作行为。

输出如下所示:

19/06/2015 16:00:26 java.math.BigDecimal signum
INFO: << signum() returns: 1
19/06/2015 16:00:26 java.math.BigDecimal layoutChars
INFO: << layoutChars(1=true) returns: 11.1099999999999994315658113919198513031005859375
19/06/2015 16:00:26 java.math.BigDecimal toString
INFO: << toString() returns: 11.1099999999999994315658113919198513031005859375
19/06/2015 16:00:26 com.runjva.demo.HelloWorld main
INFO: << main(args=[])
BigDecimal=11.1099999999999994315658113919198513031005859375
Stop at Fri Jun 19 16:00:26 PDT 2015

我希望它有所帮助。如果没有,请添加您尝试执行的操作的更多详细信息。

您唯一的机会是更改 rt.jar 的内容。引导类装入器在许多方面都很特殊,许多(但不是全部)类甚至在代理启动之前就被装入了。

可以使用 redefine 方法显式重新定义某些类。但是,并非所有引导类都可以做到这一点。

最新更新