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

  • 相关阅读:
    maven项目中各文件都没有报错,但是项目名称有红叉
    executeFind()方法和execute()方法区别
    数据库查询
    getHibernateTemplate出现的所有find方法的总结
    HQL和SQL的区别
    Java创建对象的方式
    xml中的<![CDATA[]]>和转义字符
    DWRUtil.addOptions
    dwr
    response.setHeader("Cache-Control","no-cache");的作用
  • 原文地址:https://www.cnblogs.com/caiyao/p/4989829.html
Copyright © 2011-2022 走看看