zoukankan      html  css  js  c++  java
  • 一个关于类加载器加载顺序的经典例子

    问题: 如果自己定义一个java.lang.String并运行会出现什么情况?

    我们看看下面的代码:

    1 package java.lang;
    2 public class String{
    3     public static void main(String[] args ){    
    4     }
    5 }

           大家发现什么不同了吗?对了,我们写了一个与JDK中String一模一样的类,连包java.lang都一样,唯一不同的是我们自定义的String类有一个main函数。我们来运行一下:

     java.lang.NoSuchMethodError: main
     Exception in thread "main"

    这是为什么? 我们的String类不是明明有main方法吗?

    其实联系到jvm类加载的双亲委托模型,我们就能解释这个问题了。

          运行这段代码,AppClassLoader会尝试加载java.lang.String这个类,但是根据双亲委托模型AppClassLoader会将加载java.lang.String的请求委托给ExtClassLoader,而 ExtClassLoader又会委托给最后的启动类加载器BootstrapLoader。

          启动类加载器BootstrapLoader只能加载JAVA_HOMEjrelib中的class类(即J2SE API),问题是标准API中确实有一个java.lang.String(注意,这个类和我们自定义的类是完全两个类)。BootstrapLoader以为找到了这个类,毫不犹豫的加载了j2se api中的java.lang.String。

          最后出现上面的加载错误(注意不是异常,是错误,JVM退出),因为API中的String类是没有main方法的。

    结论:我们当然可以自定义一个和API完全一样的类,但是由于双亲委托模型,使得我们不可能加载上我们自定义的这样一个类。所以J2SE规范中希望我们自定义的包有自己唯一的特色(网络域名)。还有一点,这种加载器原理使得JVM更加安全的运行程序,因为黑客很难随意的替代掉API中的代码了。

    参照:http://hxraid.iteye.com/blog/747625

  • 相关阅读:
    vsftpd的主动模式与被动模式
    Linux环境下vsftpd参数配置
    CentOS下的网络配置文件说明
    第一篇博客,随笔留念
    asp.net xml 增删改操作
    asp.net json 与xml 的基础事例
    linq 之 Distinct的使用
    【P2015】二叉苹果树(树状DP)
    【P2016】战略游戏(贪心||树状DP)
    【P2774】方格取数问题(贪心+最大流,洛谷)
  • 原文地址:https://www.cnblogs.com/caiyao/p/4989829.html
Copyright © 2011-2022 走看看