JVM中class loaderの学习


一、.class文件和jvm的关系

类的加载

所有的编译生成的.class文件都会被直接加载到JVM里面来吗(并不

首先我们明确一个概念,.class文件加载到jvm中意味着什么——类的初始化

在虚拟机规范中,我们规定,有且只有五种情况必须立即对类进行初始化

  • 创建类的实例(new一个对象)访问某个类或者接口的静态变量,对静态变量赋值,调用类的静态方法
  • reflection
  • 启动类(main),直接使用Java.exe命令来运行某个主类(main方法)
  • 动态语言支持
  • 初始化子类,父类也会被初始化

.class的加载是消耗内存的,所以当然不能一次性的把所有的类加载再运行(本来就不快,这样做不是更慢),程序的base class会完全加载到jvm里面来,至于其他的类,它们都是在需要的时候再加载的,这样是为了节省内存开销。

怎么加载

class是通过类的加载器装在到jvm里面来的,Java默认有三种类加载器

  • 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader
  • 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  • 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。

双亲委派模型

如果一个类收到了加载的请求,它首先不会自己加载这个类,而是会把请求委托给父加载器去完成,依次向上。(如果自身完成不了再依次向下,直到抛出ClassNotFound异常)

advantage:

防止内存中出现多份同样的字节码(从安全性角度来说)

已经加载过的类,下次还会请求加载吗?

class loader在成功加载某个类之后,会把得到的java.lang.Class类的实例缓存起来。如果下次再碰见该类的加载请求,类加载器会直接使用缓存的类的实例,不会再次加载

类加载器是什么?

俄罗斯套娃

类加载器的Java类和所有其他的Java类一样,都是要通过类加载器来加载的。

对于开发人员编写的类加载器来说,父类是加载该类加载器的Java类的类加载器

二、类的加载过程

加载器加载到jvm中,接下来其实又分了好几个步骤

  • 加载,查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象
  • 连接,连接又包含三块内容:验证、准备、初始化。
    • 验证,文件格式、元数据、字节码、符号引用验证;
    • 准备,为类的静态变量分配内存,并将其初始化为默认值;
    • 解析,把类中的符号引用转换为直接引用
  • 初始化,为类的静态变量赋予正确的初始值。

三、类加载器和web容器

对于运行在 Java EE™容器中的 Web 应用来说,类加载器的实现方式与一般的 Java 应用有所不同。不同的 Web 容器的实现方式也会有所不同。以 Apache Tomcat 来说,每个 Web 应用都有一个对应的类加载器实例。该类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。这是 Java Servlet 规范中的推荐做法,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类。这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的。这也是为了保证 Java 核心库的类型安全

In a Java environment, class loaders are arranged in a parent-child tree. Normally, when a class loader is asked to load a particular class or resource, it delegates the request to a parent class loader first, and then looks in its own repositories only if the parent class loader(s) cannot find the requested class or resource. Note, that the model for web application class loaders differs slightly from this, as discussed below, but the main principles are the same.

When Tomcat is started, it creates a set of class loaders that are organized into the following parent-child relationships, where the parent class loader is above the child class loader:

      Bootstrap
|
System
|
Common
/ \
Webapp1 Webapp2 ...

Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:

Bootstrap classes of your JVM

/WEB-INF/classes of your web application

/WEB-INF/lib/
.jar of your web application

System class loader classes (described above)

Common class loader classes (described above)

If the web application class loader is configured with then the order becomes:*

Bootstrap classes of your JVM

System class loader classes (described above)

Common class loader classes (described above)

/WEB-INF/classes of your web application

/WEB-INF/lib/
.jar of your web application

绝大多数情况下,Web 应用的开发人员不需要考虑与类加载器相关的细节。下面是几条简单的原则:

  • 每个 Web 应用自己的 Java 类文件和使用的库的 jar 包,分别放在 WEB-INF/classesWEB-INF/lib目录下面。
  • 多个应用共享的 Java 类文件和 jar 包,分别放在 Web 容器指定的由所有 Web 应用共享的目录下面。
  • 当出现找不到类的错误时,检查当前类的类加载器和当前线程的上下文类加载器是否正确。

ps.用的图床挂了,大家先将就着看下,后续再改

Demo

跟着博客做的一个ClassLoader小demo https://github.com/JhinQaQ/Classloader

参考资料

Java虚拟机底层原理知识总结 https://github.com/doocs/jvm

tomcat7.0 ClassLoader http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html

深入探讨Java类加载器 https://www.ibm.com/developerworks/cn/java/j-lo-classloader/

Java类加载器的使用场景有哪些?https://www.zhihu.com/question/46719811

JVM中ClassLoader的学习的更多相关文章

  1. java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制

    ClassLoader的工作机制 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有Bootstrap ClassLoader. ...

  2. 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期

    一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...

  3. JVM知识整理和学习(转载并修改)

    JVM是虚拟机,也是一种规范,他遵循着冯·诺依曼体系结构的设计原理. 冯·诺依曼体系结构中,指出计算机处理的数据和指令都是二进制数,采用存储程序方式不加区分的存储在同一个存储器里,并且顺序执行,指令由 ...

  4. JVM中垃圾回收机制如何判断是否死亡?详解引用计数法和可达性分析 !

    因为热爱,所以坚持. 文章下方有本文参考电子书和视频的下载地址哦~ 这节我们主要讲垃圾收集的一些基本概念,先了解垃圾收集是什么.然后触发条件是什么.最后虚拟机如何判断对象是否死亡. 一.前言   我们 ...

  5. 【转】JVM运行原理及JVM中的Stack和Heap的实现过程

    来自: http://blog.csdn.net//u011067360/article/details/46047521 Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’( ...

  6. [Java类加载器]Java中classLoader浅析.

    本文为在公司内部TD上写的一篇小文, 主要讲解java中classLoader基础知识, 现在拿来这里分享一下. 一.问题 请在Eclipse中新建如下类,并运行它: 1 package java.l ...

  7. 浅析JVM中的GC日志

    目录 一.GC日志的格式分析 二.运行时开启GC日志 一.GC日志的格式分析 在讲述GC日志之前,我们先来运行下面这段代码 package com.example; public class Test ...

  8. JVM的ClassLoader过程分析

    本文来自网络:深入分析Java ClassLoader原理 http://my.oschina.net/zhengjian/blog/133836 一. JVM的ClassLoader过程以及装载原理 ...

  9. JVM中的Stack和Heap

    Stack: 是内存指令区.Java基本数据类型,Java指令代码,常量都保存在stack中,方法是指令也保存在stack中. 由于stack是内存是顺序分配,而且定长,不存在内存回收问题.存取速度快 ...

随机推荐

  1. ATS项目更新(3) 远程同步到执行机器

    1: echo %time% 2: 3: 4: rem ** ipc and mapping 5: c: 6: net use x: /del 7: net use y: /del 8: net us ...

  2. 带农历日历的DatePicker控件!Xamarin控件开发小记

    原文:带农历日历的DatePicker控件!Xamarin控件开发小记 闲来无事开发了个日期选择控件,感兴趣的同学前往: https://github.com/MatoApps/Mato.DatePi ...

  3. 潜移默化学会WPF--值转换器

    原文:潜移默化学会WPF--值转换器 1. binding 后面的stringFormat的写法----连接字符串 <TextBlock Text="{Binding Path=Qty ...

  4. POJ 1986 Distance Queries LCA两点距离树

    标题来源:POJ 1986 Distance Queries 意甲冠军:给你一棵树 q第二次查询 每次你问两个点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + d ...

  5. [转]更改ejs模板后缀.ejs为.html

    三种写法 1,express老写法,3.*已经不支持 app.register('.html', require('ejs')); app.set('view engine', 'ejs'); 2, ...

  6. 【Gerrit】持续集成工具Jenkins的安装配置与使用过程中遇到的问题整理

    1.下载war包 https://jenkins.io/download/ 2.安装 java -jar jenkins.war Error: Feb 21, 2019 2:17:25 AM wins ...

  7. Win8 Metro(C#)数字图像处理--3.5图像形心计算

    原文:Win8 Metro(C#)数字图像处理--3.5图像形心计算 /// <summary> /// Get the center of the object in an image. ...

  8. duilib菜单开发遇见“0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突”

    我的程序是这样一个逻辑. 首先创建用户列表,点击列表项弹出菜单,点击菜单上“设备选项”,弹出设备列表,上面显示这个用户拥有的设备. 菜单的创建参考了这为博主的教程:http://www.cnblogs ...

  9. 笔记:Advanced Installer 打包Web应用

    原文:笔记:Advanced Installer 打包Web应用 公司要做一款增值税小产品,区别于ACME,本产品核心只有销项部分,面对的客户群是小企业,单税盒单开票机..... 我要做的主要有以下几 ...

  10. oracle 使用db_link 导入导出小结

    客户有一个需求,是将一个库中的某个用户迁移到一台新的oracle服务器上,因数据量较小,并且不涉及版本的升级,所以可以采用创建一个dblink,然后通过这个dblink直接从源库将用户数据导出并导入到 ...