学习java学到最后都要很熟悉jvm,懂得了java的运行机制,查找问题就会很快了,一般我们都是会用,还到不了精通的地步,虽说我也是个多年的java工程师,但也没有很好的掌握jvm,最近换了一家公司,之前的算是被雪藏三年,一直未于外界接触,现在我要重新拾起来,不能满足只是会用java,也要懂得其运行原理。

   学习jvm我们要知道它有哪几部分构成,各部分作用是什么:

  • 运行时数据区域

    • 程序计数器
    • java虚拟机栈
    • 本地方法栈
    • java堆
    • 方法区
    • 运行时常量池
  • 对象的创建

      程序计数器

指令执行的指向,是一块很小的内存空间,每个线程都有一个独立的程序计数器,互不影响,独立存储;如果执行native方法,则计数器为空;这个内存空间不存在OutOfMemoryError的情况。

      Java虚拟机栈

 它与程序计数器一样,是线程私有的,生命周期也同线程相同。它是java方法执行的内存模型,每个方法在执行时会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息,每一个方法从调用到执行完成的过程就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。 

java虚拟机规范中对这个区域定了两种异常情况:1.线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。
                         2.虚拟机动态扩展时,无法申请到足够的内存,就会抛出OutOfMemoryError异常。

      本地方法栈

本地方法栈与虚拟机栈所发挥的作用非常相似,区别就是虚拟机栈执行java方法,本地方法栈则为虚拟机使用native方法,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常

      java堆

java堆是jvm所管理的内存中最大的一块,java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数据组都在这里分配内存。但随着jit编译器的发展与逃逸分析技术成熟,在堆上分配也不那么绝对了。

   java堆是垃圾回收的主要区域,也称为GC堆。从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以java堆中细分为:新生代和老年代,再细分为:Eden空间,FromSurvivor空间,To Survivor空间等。无论哪个区域,存储的仍是对象实例,进一步划分的目的是为了更好的回收内存、更快的分配内存。如果堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

     方法区

方法区与java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。虽然jvm规范把方法区描述为堆的一个逻辑部分,但它有一个别名Non-Heap,目的就是与堆分开。

   java方法区无法满足内存分配需求时,将会抛出OutOfMemoryError异常。

    运行时常量池

运行时常量池是方法区的一部分,class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

   常量池是java方法区的一部分,无法满足内存分配需求时,将会抛出OutOfMemoryError异常。


对象的创建:

虚拟机遇到一条new指令时,首先要检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过,如果没有就执行相应的类加载过程。

可达性算法:

   算法的基本思想就是通过GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象没有到gc roots没有任何引用链相连时,则证明对象是不可用的。

引用类型:

强引用:Object object = new Object();这类的引用,只要强引用还存在,gc永运不会回收掉被引用对象。

软引用:描述一些还有用但并非必需的对象。在系统未发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这些回收没有足够的内存,才会抛出内存溢出异常。

弱引用:也是用来描述非必需对象的,比前两者更弱,被弱引用的关联对象只能生存到下一次垃圾收集发生之前。当gc时,无论内存是否足够,都会回收被弱引用关联的对象。

虚引用:最弱的引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。唯一目的就是能在这个对象被收集器回收时收到一个系统通知。

对象何时回收:

   对象回收至少要经历两次标记过程,如果对象在进行可达性分析后发现没有gc roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,条件就是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为"没有必要执行"。

   如果这个对象没有必要执行finalize()方法,那会被放在F-Queue的队列之中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里的执行是触发方法,并不承诺会等待它运行结束,这样是因为在finalize()中万一执行缓慢或死循环了,那F-Queue就会永久处于等待,甚至内存回收系统崩溃。如果对象在finalize()中逃过,那它就不会被回收。

无用的类:

该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。

加载该类的ClassLoader已经被回收。

该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

垃圾回收器算法:

  标记-清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收。两个不足:1.效率不高2.空间问题,这种会产生大量不连续的内存碎片,如果有大对象分配时,无法找到连续内存而不得不提前触发另一次的垃圾收集动作。

  复制算法:为了解决效率问题,一种称为“复制”的收集算法出现了,它把内存按容量划分为大小相等的两块,每次使用其中一块,当这块用完了就把对象复制到另外一块上面,然后把已使用过的内存空间一次清理掉。现在的商业虚拟机都采用这种算法,但并不是按1:1的比例来划分内存空间的,它是将内存分为一个较大的Eden空间和两个较小的Survivor空间,每次只使用Eden和一个Survivor。默认是8:1:1。

  标记-整理算法:算法同第一种,但后续不是直接对可回收的对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。

  分代收集算法:一般将java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。

深入java虚拟机学习笔记(一)的更多相关文章

  1. 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回

    <深入Java虚拟机学习笔记>- 第19章 方法的调用与返回

  2. 《深入Java虚拟机学习笔记》- 第16章 控制流

    <深入Java虚拟机学习笔记>- 第16章 控制流

  3. 《深入Java虚拟机学习笔记》- 第17章 异常

    <深入Java虚拟机学习笔记>- 第17章 异常

  4. 《深入Java虚拟机学习笔记》- 第13章 逻辑运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  5. 《深入Java虚拟机学习笔记》- 第14章 浮点运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  6. 《深入Java虚拟机学习笔记》- 第8章 连接模型

    Java虚拟机学习笔记(八)连接模型

  7. 《深入Java虚拟机学习笔记》- 第4章 网络移动性

    Java虚拟机学习笔记(四)网络移动性

  8. 《深入Java虚拟机学习笔记》- 第2章 平台无关

    Java虚拟机学习笔记(二)平台无关

  9. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  10. 深入理解java虚拟机学习笔记(一)JVM内存模型

    上周末搬家后,家里的宽带一直没弄好,跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带,可以结束一个多星期没网的痛苦日子了.这段时间也是各种忙,都一个星期没更新博客了,再不写之前那种状态和激情都要 ...

随机推荐

  1. phpstudy的80端口被占用问题

    1.查看电脑中当前程序占用的端口和程序ID 当phpstudy设置端口号为80时显示占用,在命令行中输入:netstat -ano 就可以看到当前电脑中程序占用的端口和程序ID等等信息 2.查看正在运 ...

  2. JS中数据结构之列表

    列表是一组有序的数据.每个列表中的数据项称为元素.在 JavaScript 中,列表中的元素可以是任意数据类型.列表中可以保存多少元素并没有事先限定并可以不断壮大,实际使用时元素的数量受到程序内存的限 ...

  3. 【CF1210D】Konrad and Company Evaluation(vector,图论)

    题意:有i个人,m对两两之间的关系,第i个人初始的薪水为i,有q次操作,第i次操作会把v[i]号的薪水提升成n+i 如果两个人之间存在关系,薪水高的会向薪水低的炫耀 定义u,v,w为一个三元组,当u向 ...

  4. 10.2-linux文件与目录管理

    1.1-目录的相关操作 . rm Remove (unlink) the FILE(s). -f, --force #强制删除 ignore nonexistent files, never prom ...

  5. webBrowser强制在本窗口打开,禁止在新窗口打开

    有时需要用WebBrowser加载URL,来实现某些功能.而这时,我们就不希望所打开的页面中的链接,在新窗口中打开,因为这样的话,实际上是用系统默认的浏览器打开了,从而脱离了你的WebBrowser, ...

  6. AcWing 252. 树 (点分治)打卡

    题目:https://www.acwing.com/problem/content/254/ 题意:求一棵树上,路径<=k的有多少条 思路:点分治,我们用两个指针算solve函数,首先对算出来的 ...

  7. linux从head.s到start_kernelstart_kernel之---内核解压到重定位分析

    一: arm linux 内核生成过程 1. 依据arch/arm/kernel/vmlinux.lds 生成linux内核源码根目录下的vmlinux,这个vmlinux属于未压缩,带调试信息.符号 ...

  8. mybatis 查询一对一

    官方文档 Mapper接口 public interface UserMapper { User getUser(int userId); } public interface ArticleMapp ...

  9. HTML段落,换行,字符实体

    HTML段落,换行,字符实体 html段落 <p>标签定义一个文本段落,一个段落含有默认的上下间距,段落之间会用这种默认间距隔开,代码如下: <!DOCTYPE html> & ...

  10. Python开发简介

    年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承 . 最新的TIOBE排行榜,Python已经占据世界第四名的位置, Python崇尚优美 ...