类加载详解

一 JAVA_HOME、path、classPath的区别

CLASSPATH是Java中最重要的概念之一,但通常都被忽视了。不清楚classpath就不会知道java如何定位你的类文件。

1、JAVA_HOME指的是你JDK安装的位置,一般默认安装在C盘,如

C:\Program Files\Java\jdk1.8.0_91

2、path

PATH=%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;%PATH%;

  1. 设置path的作用是让操作系统可以找到JDK命令(指定了JDK命令搜索路径);path环境变量原来Windows里面就有,只需修改一下,使他指向JDK的bin目录,这样在控制台下面编译、执行程序时就可以直接使用java、javac命令了;
  2. 将程序路径包含在PATH当中后,在命令行窗口就可以直接键入它的名字了,而不再需要键入它的全路径,如果我们用到的javac和java两个命令。

3、classPath

CLASSPATH=.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar

  1.  告诉类装载器到哪里去寻找第三方提供的类和用户定义的类。JVM和其他JDK工具通过依次搜索平台库,扩展库,和类路径来查找类。最通俗可以这样理解:path是操作系统用 ,classpath是java编译器用。
  2. 一看就是指向jar包路径。需要注意的是前面的.;,.代表当前目录。
  3.  classpath它是javac编译器的一个环境变量。它的作用与import、package关键字有关。当你写下improt java.util.*时,编译器面对import关键字时,就知道你要引入java.util这个package中的类---就是类的路径所在,你要的类到哪里找。

4、环境变量的设置与查看


echo %JAVA_HOME%

echo %PATH%

echo %CLASSPATH%

5、参考文献:

(1)百度知道 关于java_home,classpath,path和javac的问题 https://zhidao.baidu.com/question/497329193350662564.html

(2)csdn  一看你就懂,超详细java中的ClassLoader详解  https://blog.youkuaiyun.com/briblue/article/details/54973413

(3)博客园 path、classpath理解 https://www.cnblogs.com/huahua035/p/6598863.html

(4)技术之家 你理解java中classpath到底是什么,怎么理解 http://www.jszja.com/contents/14/705.html

(5)csdn 关于JAVA项目中CLASSPATH路径详解 https://blog.youkuaiyun.com/qq_16605855/article/details/72909785

(6)csdn Java入门实例classpath及package详解 https://blog.youkuaiyun.com/martin_liang/article/details/7626571

(7)csdn  Java中的classpath https://blog.youkuaiyun.com/weixin_34138377/article/details/89995627

(8)博客园 范仁义 Java中classpath配置 https://www.cnblogs.com/Renyi-Fan/p/6876446.html

二 JVM类加载机制

注意点:用eclipse的打包工具将ClassLoaderTest输出成jre/lib/ext目录下的lqqheima.jar包,再在eclipse中运行这个类,运行结果显示为ExtClassLoader。此时的环境状态时classpath目录有ClassLoaderTest.class,ext/lqqheima.jar包中也有ClassLoaderTest.class,这个时候我们就需要了解类加载的具体过程和原理了。以上情况验证的结果是打印出显示加载ClassLoaderTest.class的加载器是ExtClassLoader,而不再是之前的AppClassLoader加载器了。

JVM中包括集中类加载器:

  1 BootStrapClassLoader 引导类加载器。其实类加载器也是类,也需要加载,这些BootStrapClassLoader以外的类加载器,就是由BootStrapClassLoader加类。

  2 ExtClassLoader 扩展类加载器

  3 AppClassLoader 应用类加载器

  4 CustomClassLoader 用户自定义类加载器

  他们的区别上面也都有说明。需要注意的是,不同的类加载器加载的类是不同的,因此如果用户加载器1加载的某个类,其他用户并不能够使用。

当JVM运行过程中,用户需要加载某些类时,会按照下面的步骤(父类委托机制)

  1 用户自己的类加载器,把加载请求传给父加载器,父加载器再传给其父加载器,一直到加载器树的顶层。

  2 最顶层的类加载器首先针对其特定的位置加载,如果加载不到就转交给子类。

  3 如果一直到底层的类加载都没有加载到,那么就会抛出异常ClassNotFoundException。

因此,按照这个过程可以想到,如果同样在CLASSPATH指定的目录中和自己工作目录中存放相同的class,会优先加载CLASSPATH目录中的文件。

三 Tomcat 如何实现自己独特的类加载机制?

所以,Tomcat 是怎么实现的呢?牛逼的Tomcat团队已经设计好了。我们看看他们的设计图:

      我们看到,前面3个类加载(Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader)和默认的一致。不一样的是,Tomcat自己定义多个类加载器,它们分别是:CommonClassLoader、CatalinaClassLoader、SharedClassLoader、WebApp ClassLoader、JasperLoader。其中:

  1. CommonClassLoader加载:%TOMCAT_HOME%/common/*中的Java类库;Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;
  2. CatalinaClassLoader加载:%TOMCAT_HOME%/server/*中的Java类库;Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见;
  3. SharedClassLoader加载:%TOMCAT_HOME%/shared/*中的Java类库;各个Webapp共享的类加载器,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见;
  4. WebApp ClassLoaderl加载:%TOMCAT_HOME%/WebApp/AppName/WEB-INF/*中的Java类库;各个Webapp私有的类加载器,加载路径中的class只对当前Webapp可见;

其中WebApp类加载器和Jsp类加载器通常会存在多个实例,每一个Web应用程序对应一个WebApp类加载器,每一个JSP文件对应一个Jsp类加载器。

      从图中的委派关系中可以看出:

  1. CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用;
  2. 而CatalinaClassLoader和Shared ClassLoader自己能加载的类则与对方相互隔离;
  3. WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离;
  4. 而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能;  

      注意:在tomcat 6之后,common、server、shared,这3个目录已经合并到根目录(TOMCAT_HOME)下的lib目录下

通俗易懂理解JAVA虚拟机(一)——类加载详解_第8张图片

      好了,至此,我们已经知道了tomcat为什么要这么设计,以及是如何设计的,

      问题1:那么,tomcat 违背了java 推荐的双亲委派模型了吗?答案是:违背了。 我们前面说过:双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应当由自己的父类加载器加载。很显然,tomcat 不是这样实现,tomcat 为了实现隔离性,没有遵守这个约定,每个webappClassLoader加载自己的目录下的class文件,不会传递给父类加载器。双亲委派机制如下图所示:

通俗易懂理解JAVA虚拟机(一)——类加载详解_第7张图片

      问题2:我们扩展出一个问题:如果tomcat 的 Common ClassLoader 想加载 WebApp ClassLoader 中的类,该怎么办?看了前面的关于破坏双亲委派模型的内容,我们心里有数了,我们可以使用线程上下文类加载器实现,使用线程上下文加载器,可以让父类加载器请求子类加载器去完成类加载的动作。牛逼吧。

四 参考文献

1、博客园 图解Tomcat类加载机制(阿里面试题) https://www.cnblogs.com/aspirant/p/8991830.html

2、博客园 【JVM】浅谈双亲委派和破坏双亲委派   https://www.cnblogs.com/joemsu/p/9310226.html

3、通俗易懂理解JAVA虚拟机(一)——类加载详解  https://www.it610.com/article/1288470555321769984.htm

4、博客园 JAVA基础加强(张孝祥)_类加载器、分析代理类的作用与原理及AOP概念、分析JVM动态生成的类、实现类似Spring的可配置的AOP框架 https://www.cnblogs.com/heartstage/p/3390447.html  

     csdn Java类加载器深入讲解--张孝祥老师 https://blog.youkuaiyun.com/lushuner/article/details/41014191

     csdn 黑马程序员_张孝祥_Java基础加强_类加载器 https://blog.youkuaiyun.com/longlangss/article/details/9930135

5、csdn 类加载器 https://blog.youkuaiyun.com/liuqingqian001/article/details/6178884?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control

五 类加载器应用案例1:Tomcat类加载器调用顺序研究

网上很多资料(包括官方文档)都说有common、system这些类加载器。但是我调试源码的时候并没有看到这些类加载器。 tomcat version:8.5.42。

本文研究两个问题:

1、JAVA_HOME/lib/ext和/WebApp/WEB-INF/lib中有相同全限定类名时,加载谁的类。答:前者

2、加载类的过程中classloader的大致调用过程。WebappClassLoaderBase(tomcat的)->ExtClassLoader->BootStrapClassLoader
————————————————
参考文献:csdn Tomcat类加载器调用顺序研究 https://blog.youkuaiyun.com/m1f2c3/article/details/112424408

六 类加载器应用案例2:Tomcat的类加载顺序的实现

其实之所以为写这篇文章的原因,主要是前段时间,因为使用第三方的一些库,需要将这些库放到JDK的ext目录,由Java的ExtClassLoader进行加载,第三方库也是用了日志框架,而且使用的是slf4j,所以要使用这个第三方库,必须将slf4j-api.jar这个slf4j的接口包放到ext目录下。将这个日志放到slf4j-api.jar放到ext目录下,接着应用层的日志打印不出来,应用层的日志包也是使用slf4j,应用是在Tomcat中跑的。
————————————————

参考文献:csdn Tomcat的类加载顺序的实现 https://blog.youkuaiyun.com/strive_or_die/article/details/100850378

七 附1:apache-tomcat-5.5.17目录结构示意图

八 附2:apache-tomcat-7.0.103目录结构示意图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值