深入浅出的JVM

发布时间:2020-06-02 02:53:09 作者:原生zzy
来源:网络 阅读:784

一、jvm的组织结构

  (1)jvm 和系统调用之间的关系

深入浅出的JVM
相应的名词解释
   - 类加载器:在jvm启动或者类运行时将需要的class加载到jvm内存中
   - 执行引擎:负责执行class文件中包含的字节指令
   - 内存区:是在jvm运行的时候操作锁分配的内存区。运行时内存区分五个部分:堆、方法区、栈、本地方法栈、程序计数器,
   - 本地方法接口:主要是调用c或者c++实现的本地方法及返回结果。

  (2)jvm 的内存结构

深入浅出的JVM
   jvm内存结构主要由三大块:堆内存、方法区和栈。
   堆内存:是jvm中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三个部分:Eden 空间(对相关刚刚被创建时存放的位置)、From Survivor() 空间、To Survivor(存货下来的对象的存放区域) 空间,默认情况下年轻代按照 8:1:1 的比例来分配。
   方法区(永久代):存储信息、常量、静态变量等数据,是线程共享的区域,为与java堆区分,方法区还有一个别名Non-Heap(非堆) jvm各区域的作用。
   :又分为java虚拟机栈和本地方法栈和程序计数器,主要用于方法的执行。

  (3)各个区域参数调控

深入浅出的JVM
堆内存的设置:

-Xms:设置堆的最小空间大小
-Xmx:设置堆的最大空间大小
-XX:NewSize 设置新生代最小空间大小
-XX:MaxNewSize:设置新生代最大空间大小
-XX:PermSize 设置永久代最小空间大小
-XX:MaxPermSize 设置永久代最大空间大小
-Xss 设置每个线程的堆栈大小
没有直接设置老年代的参数,但是可以设置堆空间大小和新生代空间大小两个参数来间接控 制:老年代空间大小=堆空间大小-年轻代大空间大小

二、jvm各内存区域的作用

(1)各个区域的概述:

(2)java 堆(heap):

  对于大多数应用来说,Java 堆(Java Heap)是 Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
  java堆是垃圾收集器管理的主要区域,因此很多时候也被成为GC堆。如果从内存回收的角度看,由于现在收集器基本都是采用分代收集算法,所以java堆中还可以划分:新生代和老年代;在细一点的划分:新生代又包括:Eden 空间、From Survivor 空间、To Survivor 空间。
  如果在堆中没有内存完成实例分配(堆中没有内存装得下对象),并且堆也无法再扩展时,将会抛出 OutOfMemoryError 异常。
深入浅出的JVM
补充(新生代到老年的过程):大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC,此时对象会进入survivor区,当对象满足一些条件后会进入老年代。
  - 长期存活的对象将进入老年代:虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1。对象在Survivor区中每“熬过”一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁),就将会被晋升到老年代中。对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。
  - 如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。
  - 虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存复制。

(3)方法区(method area):

   -方法区与java一样,是各个线程的共享的内存区域,它用于存储被jvm加载的类信息、常量、静态变量、及时编译器编译后的代码等数据。
  jvm规范对这个区域的限制非常宽松,除了和java堆一样不需要连续的内存和可以选择固定大小,还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,到哪并非数据进入的方法区就“永远”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收 “成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。
  根据 Java 虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出 OutOfMemoryError 异常。

(4)程序计数器:

  程序计数器时一小块的内存空间,它的作用可以看做是当前程序所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器完成。
  由于 Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在 任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程 中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
  如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是 native 方法(调用时使用底层的指令),这个计数器值则为空(Undefined)。
  此内存区域是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。

(5)java虚拟机栈:

  Java 虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是 Java 方法执行的内存模型:每个方法被执行的时候 都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
深入浅出的JVM
  局部变量表存放了编译期可知的各种基本数据类型,局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
  关于java虚拟机栈的异常:1) 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverflowError 异常 2) 如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出 OutOfMemoryError 异常。

(6)本地方法栈:

  使用native修饰的方法,则存储在本地方法栈中。与虚拟机栈一样,本地方法栈 区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常。

三、jvm的垃圾回收机制介绍

(1)jvm 垃圾回收介绍:

  垃圾收集Garbage Collection通常被称为“GC”,它诞生于1960年MT的Lisp语言。Jvm中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的 进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 Java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的。

(2)垃圾收集器(Garbage Collection)的介绍:

  GC其实是一种自动的内存管理工具器行为主要包括2个步骤:在和Java堆中,为新的创建的对象分配空间、回收没有用的对象的内存空间

(3)实现多种GC的好处:

  Java 平台被部署在各种各样的硬件资源上,其次,在 Java 平台上部署和运行着各种 各样的应用,并且用户对不同的应用的性能指标(吞吐率和延迟)预期也不同,为了满足不同 应用的对内存管理的不同需求,JVM 提供了多种 GC 以供选择。
  GC的性能指标主要包括
   - 最大停顿时长:圾回收导致的应用停顿时间的最大值
   - 吞吐率:垃圾回收停顿时长和应用运行总时长的比例
   例:一次应用程序运行了60s,然后GC的时长为2s(进行了4次GC:0.5,0.8,0.2,0.5),那么最大的停顿时长为:0.8,吞吐率为:(60-2)/60
  GC的种类大概分为
   - 序列化GC:适合占用内存少的应用
   - 并行GC或者吞吐率GC,适合占用内存较多,多 CPU,追求高吞吐率的应用。
   - 并发GC:适合占用内存较多,多 CPU 的应用,对延迟有要求的应用。
   并行:指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
   并发:指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交 替执行)。

(4)对象存活的判断:

   - 引用计数:每个对象有一个引用计数属性,新增一个引用时计数加 1,引用释放时计数减 1,计数为 0 时可以回收。此方法简单,缺点是无法解决对象相互循环引用的问题。
   - 可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为 引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的不可达对象。
深入浅出的JVM
可达对象:通过根对象进行引用搜索,最终可以达到的对象。
不可达对象:通过根对象进行引用搜索,最终没有被引用到的对象。
Java 语言中,GC Roots 包括:

推荐阅读:
  1. 深入浅出MongoDB
  2. JVM是什么?JVM的方法有哪些?

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jvm 深入浅出 j

上一篇:电脑 蓝屏 原因

下一篇:mariadb的日志

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》