一、运行时数据区域

1、程序计数器:

  • 当前线程执行字节码的行号指示器(通过改变计数器的值来选择下条需要执行的字节码指令)
  • 每个线程有独立的程序计数器(线程私有,为了切换线程时能恢复到挣钱的执行位置)
  • 如果执行java方法,计数器记录正在执行的字节码指令地址。如果执行的是Native方法,计数器为空。
  • 唯一没规定任何OutOfMemoryError情况的区域。

2、虚拟机栈

  • 为执行Java方法服务
  • 线程私有,声明周期跟线程一致
  • 一个Java方法执行到结束的过程:栈帧从入栈到出栈的过程
  • 栈帧存储局部变量表(包括基本数据类型和对象的引用类型)、操作栈、动态链接、方法出口等信息
  • 异常:线程请求的栈深度大于虚拟机允许的深度,抛出StackOverflowError。虚拟机动态扩展过程中无法申请到足够的内存,会抛出OutOfMemoryError异常。

3、本地方法栈

  • 为虚拟机用到的Native方法服务
  • 也会抛出StackOverflowError和OutOfMemoryError的异常

4、Java堆

  • 用来存储对象的实例
  • 所有线程共享的一块内存区域
  • 从内存回收的角度可以分为新生代和老年代

5、方法区

  • 存放被虚拟机加载的类信息、常量、静态变量等
  • 线程共享

6、运行时常量池

  • 方法区的一部分
  • 存放编译期生成的各种字面量和符号引用

二、垃圾回收(GC)

  • 哪些内存需要回收
  • 什么时候回收
  • 怎么回收

1、判断对象是否存活

1、引用计数法:

  • 给Java对象添加一个引用计数器,每当有一个地方引用它时,计数器+1;引用失效则-1。当计算器不为0时,判断对象存活
  • 缺点:如果两个对象相互循环引用时,因为计算器不为0,不能被回收。实际上对象应该被回收。

2、可达性分析算法:

(1)原理:
把"GC Roots"的对象作为起点,然后向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,即该对象不可达,也就说明此对象是不可用的。

(2)可作为GC Root对象:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区常量引用的对象
  • 本地方法栈中JNI引用的镀锡

3、判断一个类可回收:

  • 该类所有实例对象被回收
  • 加载该类的ClassLoader已经被回收
  • 该类对应的Class对象没被引用,无法通过反射访问该类的方法

2、引用类型

通过引用的强度分为强、软、弱、虚四种引用类型

  • 强应用:一般Object b=new Object()这类引用,只要强引用存在,GC就不会回收被引用的对象。
  • 软引用:系统在发生内存溢出之前,会将这些对象二次回收。如果还没足够内存,才会抛出内存溢出异常。通过SoftReference来实现。
  • 弱引用:GC回收时,无论内存是否足够,都会收会被弱引用关联的对象。通过WeakReference来实现。
  • 虚引用:作用是在对象被回收时收到一个系统通知。通过PhantomReference来实现。

3、垃圾收集算法

1、标记-清除算法:标记出所有需要回收的对象,标记完统一清除被标记的对象。

缺点:

  • 标记和清理的效率不高
  • 标记清除后会产生大量不连续的内存碎片

2、复制算法:将内存分为大小相等的两块,每次只用一块,当这一块内存用完,将存活对象复制到另一块,将使用过的内存一次清理。

优缺点:

  • 不会产生内存碎片的问题
  • 缺点是将内存缩小到了之前的一半
  • 在对象存活率高时进行多次复制操作,效率会低。

3、标记-整理算法:标记需要回收的对象,将存活对象向一端移动(整理),清理掉可回收的对象。

4、分代收集算法:根据对象存活周期不同,将Java堆内存分为新生代和老年代。

  • 新生代:只有少量对象存活,使用复制算法。
  • 老年代:大量对象存活,使用标记清除或者标记整理算法。

三、类加载机制

1、类加载时机

1、定义:
把Class文件加载到内存中,并对数据进行校验、解析和初始化,行成可被虚拟机直接使用的Java类型。类从被加载到虚拟机内存中开始,到卸载出内存结束。

2、生命周期:

  • 加载
  • 验证
  • 准备
  • 解析
  • 初始化
  • 使用
  • 卸载 加载、验证、准备、初始化、卸载的顺序确定。

3、需要对类进行初始化的场景

  • new实例化对象、读取或设置类的静态字段,调用类的静态方法(被final修饰,已在编译期将结果放入常量池的静态字段除外)
  • 对类进行反射
  • 初始化一个类,若父类还没初始化,先触发父类的初始化
  • 需指定一个执行的主类(包含main方法的类),虚拟机先初始化该类
  • JDK1.7动态语言,MethodHandle实例解析结果REF_getStatis、REF_putStatis、REF_invokeStatis的方法句柄

4、不会方法初始化的场景:
所有引用类的方式不会触发初始化,例如子类引用父类的静态字段,只触发父类初始化。

5、接口初始化和类初始化的区别:
接口初始化时,不要求其父类接口全部完成初始化。

2、类加载过程

包括加载、验证、准备、解析、初始化5步

1、加载:

  • 通过类全限定名获取定义该类的二进制字节流
  • 将字节流的静态存储结构转换为方法区的运行时数据结构
  • 内存中生成该类的Class对象,作为访问该类数据的入口

2、验证:

  • 文件格式验证,验证字节流是否符合Class文件格式规范
  • 元数据验证,对字节码描述的信息进行语义分析
  • 字节码验证,确定语义合法
  • 符号引用验证,对常量池符号引用校验

3、准备: 为类变量(static修饰的变量)分配内存并设置变量初始值

4、解析: 将常量池符号引用替换为直接引用(直接指向目标的指针)的过程

5、初始化: 开始执行类中定义的Java代码

3、类加载器

同一个Class文件,被两个不同的类加载器加载,这两个类不相等。相等包括equals、instanceOf、isInstance方法返回的结果。

1、类别:

  • 启动类加载器(Bootstrap ClassLoader):加载<JAVA_HOME>\lib目标,或者被-Xbootclasspath参数指定的路径,可被虚拟机识别的类库
  • 扩展类加载器(Extension ClassLoader):加载<JAVA_HOME>\lib\ext目录,或被java.ext.dirs系统变量指定的路径的类库
  • 应用类加载器(Application ClassLoader):加载ClassPath上指定的类库

2、双亲委托机制
除了顶层的类加载器外,其他的类加载器都有自己的父类加载器。父子之间通过组合来复用父加载器代码。
双亲委托机制的工作流程:一个类加载器收到类加载的请求,首先将请求委托给父类加载器去完成,最终所有加载请求都会传递给顶层的启动加载器中。当父加载器发现未找到所需的类而无法完成加载请求时,子加载器才尝试去加载。

ClassLoader

protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
//检查请求的类是否已经被加载
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//让父类加载器去尝试加载
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
//父类加载器抛异常
} if (c == null) {
//然后调用自身的findClass方法来进行类加载
c = findClass(name);
}
}
return c;
}

  • 先检查是否被加载过,如果没有则调用父加载类去加载
  • 父加载器为空,则调用启动类加载器
  • 父加载器加载失败,则抛出ClassNotFoundException异常
  • 然后去调用自身的findClass方法去进行类加载

深入理解Java虚拟机(一)的更多相关文章

  1. 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具

    上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...

  2. 《深入理解 java虚拟机》学习笔记

    java内存区域详解 以下内容参考自<深入理解 java虚拟机 JVM高级特性与最佳实践>,其中图片大多取自网络与本书,以供学习和参考.

  3. (1) 深入理解Java虚拟机到底是什么?

    好文转载:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机   作为一个Java程序员,我们每天都在写Java ...

  4. 深入理解java虚拟机(7)---线程安全 & 锁优化

    关于线程安全的话题,足可以使用一本书来讲解这些东西.<Java Concurrency in Practice> 就是讲解这些的,在这里 主要还是分析JVM中关于线程安全这块的内容. 1. ...

  5. 深入理解java虚拟机(6)---内存模型与线程 & Volatile

    其实关于线程的使用,之前已经写过博客讲解过这部分的内容: http://www.cnblogs.com/deman/category/621531.html JVM里面关于多线程的部分,主要是多线程是 ...

  6. 深入理解java虚拟机(5)---字节码执行引擎

    字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...

  7. 深入理解java虚拟机(4)---类加载机制

    类加载的过程包括: 加载class到内存,数据校验,转换和解析,初始化,使用using和卸载unloading过程. 除了解析阶段,其他过程的顺序是固定的.解析可以放在初始化之后,目的就是为了支持动态 ...

  8. 深入理解java虚拟机(1)------内存区域与内存溢出

    在C++领域,关于C++的内存存储,结构等等,有一本书:深度探索C++对象模型,讲解的非常透彻. 而Java确把这一工作交给了虚拟机来处理. 我们首先来看看关于内存的问题. 1.问题: 1)java ...

  9. 什么是HotSpot VM & 深入理解Java虚拟机

    参考 http://book.2cto.com/201306/25434.html 另外,这篇文章也是从一个系列中得出的: <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> ...

  10. 【Todo】深入理解Java虚拟机 读书笔记

    有一个在线系列地址 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> http://book.2cto.com/201306/25426.html 已经下载了这本书(60多M ...

随机推荐

  1. CentOS7安装MySQL5.7常见问题

    下载与安装 亲测有效: https://www.linuxidc.com/Linux/2016-09/135288.htm 设置MySQL服务开机自启动 注意,CentOS6和7有一点不同:CentO ...

  2. shell常用命令大全

    目录: 一.文件目录类命令 二.文件压缩和归档类命令 三.系统状态类命令 四.网络类命令 五.其他 一.文件目录类命令 1.查看联机帮助信息. man命令.#man ls info命令. #info ...

  3. idea mac快捷键

    mac快捷键 alt+f7查找变量方法使用的地方 F3添加书签 Ctrl + O快捷覆写方法 Alt + F3 添加书签标识 command + F3 显示书签 command + Shift + A ...

  4. jQuery源代码解析(3)—— ready载入、queue队列

    ready.queue放在一块写,没有特殊的意思,仅仅是相对来说它俩可能源代码是最简单的了.ready是在dom载入完毕后.以最高速度触发,非常实用. queue是队列.比方动画的顺序触发就是通过默认 ...

  5. mybatis动态sql中的两个内置参数(_parameter和_databaseId)

    mybatis动态sql中的两个内置参数(_parameter和_databaseId)   <!-- mybatis动态sql的两个内置参数           不只是方法传递过来的参数可以被 ...

  6. jquery 回车事件实现代码

    // 键盘事件 1.keydown()  keydown事件会在键盘按下时触发. 2.keyup()  keyup事件会在按键释放时触发,也就是你按下键盘起来后的事件 3.keypress()  ke ...

  7. 解决okhttp的java.lang.IllegalStateException: closed错误

    错误如下 原因为OkHttp请求回调中response.body().string()只能有效调用一次,而我使用了两次: String result = response.body().string( ...

  8. 通过 Spark R 操作 Hive

    作为数据工程师,我日常用的主力语言是R,HiveQL,Java与Scala.R是非常适合做数据清洗的脚本语言,并且有非常好用的服务端IDE——RStudio Server:而用户日志主要储存在hive ...

  9. Javascript导航菜单13则

    来源:http://www.noupe.com/ajax/13-awesome-java-script-css-menu.html翻译:http://parandroid.com下面为你准备了13个利 ...

  10. RIP路由协议及工作原理

    RIP路由协议及工作原理 RIP(Routing information Protocol,路由信息协议)是应用较早.使用较普遍的内部网关协议(Interior Gateway Protocol,IG ...