JVM详细解析(Java 8 HotSpot VM内存分配、GC)

JVM详细解析(Java 8 HotSpot VM内存分配、GC)

1 简介

JVM是Java虚拟机的简称,是为了保证Java程序能运行在不同操作系统上的一个虚拟机器,它不直接与硬件交互,而是运行在操作系统上,所有的Java线程都会调用操作系统的线程,通常是C线程,所有的系统线程均通过CPU进行管理与分配。
在这里插入图片描述

2 JVM角色

  • 虚拟机Stack

  • 本地方法栈

  • 程序计数器

  • 方法区

  • 类加载器

  • 执行引擎

2.1 线程私有内存

线程的私有内存包括虚拟机栈、本地方法栈、程序计数器。

  1. 虚拟机栈通常是在线程启动之前被创建,用来存储方法、局部变量、8种基本数据类型、操作状态(出、入栈)、方法动态链接,方法出口,调用一个方法,伴随着方法的入栈,结束方法,伴随着出栈,每个方法在栈中都意味着一个栈帧,他与线程同声明周期。
  2. 本地方法栈,与虚拟机栈的功能相当,只不过存储的是本地方法的相关内容,native 方法通常是用来与硬件交互的,现在已经很少使用了,通常只出现在用Java驱动硬件的场景,如打印机等等。
  3. 程序计数器,这个程序计数器是用来保存线程下一个执行链接的,是线程运行字节码的行号计数器,用来表示线程执行的进度,这里是不会发生OOM的

2.2 线程共享区域

线程共享区域主要包括堆、元空间(方法区)

  1. 堆,这是存储对象实例的地方,是GC的主要区域,由于Java的GC属于分代回收,所以堆可以按照**(1:2)[young:old]**,同时young又按照(8:1:1)[eden,s-from,s-to]进行内存分配。
  2. 之前叫方法区,主要存储(常量、静态变量、类信息、运行时常量池),但是后来改成MetaSpace后将运行时常量池划、静态变量、常量分到的一部分,同时Class类信息被分到了native内存,方法区这里基本不会发生GC,就算GC也只是简单的常量回收以及类的卸载,收益很小。

2.3 类加载器(双亲委派机制)

ClassLoader叫做类加载器,通常分为自带的类加载器

  • 启动类加载器
    • 扩展类加载器
      • 系统类加载器(应用程序加载器)
        • 用户自定义加载器

类加载器遵循双亲委派机制,通常当一个类来了之后,不会立马交给当前类加载器加载,首先优先交给父类加载器进行尝试加载,如果在该加载器的类路径下加载不到该类,那么就交给下级进行加载。

rt.jar是java运行时的核心jar包,里面包含lang,util等核心包,通常java.lang.Object这个类最终会交给启动类加载器进行加载,这样的好处是不管使用哪个加载器加载该类,最终的Object类都是一致的。

3 java GC

首先Java GC主要发生在Heap堆共享内存中,之前讲过堆实际上是分为如下几层:

  • young:1
    • eden:8
    • survivor_from :1
    • survivor_to :1
  • old :2

:后面为内存空间所分配的比例

3.1 minor GC

这是发生在young区域的GC,通常GC算法使用复制算法,简单的流程为复制-清除-替换

  1. 将eden与survivor from区域的可回收对象进行标记,将不可回收的对象全部复制survivor to区域,同时将年龄+1,如果survivor to的空间不够,那么将数据移动到old区域。
  2. 然后将标记需要被清除的数据进行清除。
  3. 将survivor from 与survivor to进行位置的交换。

3.2 full GC(major GC)

major GC主要发生在老年代,通常是old区域满了之后才开始进行。

如果在FullGC完成之后依然无法进行对象的保存,那么就会产生OOM(java.lang.OutOfMemoryError: java heap space 异常)!通常有以下原因。

  • Java虚拟机分配的堆内存不够,可以通过 -Xms -Xmx进行堆内存的设置。
  • 代码中创建了大量的对象,且这些对象不能被垃圾收集器回收,仍然处于被引用的状态。

4 常用的JVM调优

4.1 Java 7

  • -Xms :最小Heap内存设置
  • -Xmx:最大heap内存设置
  • -Xmn:young区域内存设置
  • -XX:PermSize:永久代(方法区)内存设置
  • -XX:MaxPermSize:永久代(方法区)最大内存设置

4.2 Java 8

  • -Xms :最小Heap内存设置,默认为物理内存的1/64.
  • -Xmx:最大heap内存设置,默认为物理内存的1/4.
  • -Xmn:young区域内存设置

在Java8中,永久代(方法区)已经被移除,被一个叫做MetaSpace的区域替代,两者本质相同,只不过,MetaSpace已经不属于JVM的内存区域,而是本地内存的一部分,受操作系统控制,也被称为non-heap内存,从此JVM能加载多少类的元数据就不受PermSize的控制了。

4.3 常用的VM参数示例

-Xms1024m -xmx1024m -XX:PrintGcDetails #很多Java编写的组件,框架都有对用的JVM调优以及GC优化
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值