JAVA bootstrap ClassLoader和JAVA核心API替换 《java -Xbootclasspath/p:F:\myinteger.jar MyIntegerTest》

http://blog.csdn.net/sureyonder/article/details/5726994

本文整理于上面文章,并经过自己实践,java的核心API类库,比如 java.lang.Integer的确可以通过设置Xbootclasspath来替换之,谢谢原作者的分享


JAVA bootstrap ClassLoader和JAVA核心API替换

1 双亲委派模型

JAVA虚拟机规范定义了两种类型的类装载器

-启动类装载器和用户自定义类装载器,

启动类装载器是JAVA虚拟机实现的一部分,用C/C++编写的。

通过继承ClassLoader类,用户可以创建自定义的类装载器来完成特定要求的加载。

JAVA虚拟机已经创建了2个自定义类装载器扩展类装载器系统类装载器


 每一个用户自定义的类装载器在创建时被分配一个“双亲”parent类装载器。如果没有显示地传递一个双亲类装载器给用户自定义的类装载器的构造方法,系统类装载器就默认被指定为双亲。

如果传递到构造方法的是一个已有的用户自定义类装载器的引用,该用户自定义类装载器就作为双亲;

如果向构造方法传递了 null,启动类装载器BootStrap就是双亲


 在此模型下,启动类装载器可以抢在扩展类装载器之前去装载类,而扩展类装载器可以抢在系统类装载器之前去装载那个类,系统类装载器又可以抢在网络类装载器之前去装载它。

这样,使用双亲-孩子委派链的方式,启动类装载器会在最可信的类库-核心JAVA API-中首先检查每个被装载的类型,然后,才依次到扩展路径、系统类路径中检查被装载的类型文件。用这种方法,类装载器的体系结构就可以防止不可靠的代码用它们自己的版本来替代可以信任的类。


2 替换JAVA核心API

默认情况下,bootstrap启动类装载器装载jre/lib目录下的核心类。

通过在命令行下使用参数-Xbootclasspath,可以让bootstrap启动类装载器装载的我们自己的类

我们也可以修改JAVA核心类API,然后让启动类装载器优先装载修改的API类,就可以替换原来的API

  我们拷贝java.lang.Integer类的源代码,做如下修改:

    public Integer(int value) {
      System.out.println( "Customer Integer Initialized" );
      this.value = value;
    }

然后在下面的MyIntegerTest.java中调用java.lang.Integer类:

public class MyIntegerTest
{
  public static void main( String[] args )
  {
    System.out.println( new Integer( 100 ) );
  }
}

编译新的java.lang.Integer类之后,用jar命令生成myinteger.jar文件,然后在命令行上运行下面命令:


java -Xbootclasspath/p:myinteger.jar MyIntegerTest

  输出如下:

  Customer Integer Initialized
  100

由此可见,修改后的java.lang.Integer类替换了JRE的java.lang.Integer类


=================================================================================

---------------------注意Xbootclasspath参数后米按用 : 用 /a: 或者用 /p: 的区别

    -Xbootclasspath:<用 ; 分隔的目录和 zip/jar 文件>
                      设置搜索路径以引导类和资源

注意,如果用这个参数,不用下面的/a或者/p的话,就只会从这里制定的目录和文件里加载了,就不会到 jdk默认的\jre\lib\* 下加载 核心类库了
    -Xbootclasspath/a:<用 ; 分隔的目录和 zip/jar 文件>
                      附加在引导类路径末尾
    -Xbootclasspath/p:<用 ; 分隔的目录和 zip/jar 文件>
                      置于引导类路径之前

----------------------


下面是自己在命令行和 Eclipse上执行的结果


之所以多出现了几次*UPDATE*输出,我理解是因为jdk加载核心类库时,有些api也调用了Integer(即修改过的Integer)


F:\javadata\syslib>java-Xbootclasspath/p:myinteger.jar MyIntegerTest
Customer Integer Initialized, UPDATE INTEGER=======================
Customer Integer Initialized, UPDATE INTEGER=======================
Customer Integer Initialized, UPDATE INTEGER=======================
100
Customer Integer Initialized, UPDATE INTEGER=======================
100
F:\javadata\syslib>


注意,这里用这个参数 -D的参数,在命令行下不好用,试验过,只有用 -X才好用

F:\javadata\syslib>java -verbose -Dbootclasspath/p:F:\myinteger.jar MyIntegerTest



下面是自己在Eclipse上进行的设置

Run Configrations --》 VM arguments: --》 

-Xbootclasspath/p:F:\myinteger.jar; -verbose



=================================================================================



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值