JavaJVM · Java虚拟机原理 · JVM上语言·框架· 生态系统

JVM内存管理总结

2019-06-09  本文已影响2人  luckyHarry4

前言

“Write Once Run anywhere” 是得益于JVM,工作了将近一年的时间也明白了,最重要的还是思想结构和底层的实现,因为就算新技术层出不穷,它们也只不过是在锦上添花而已。
本文是我是从《深入理解Java虚拟机》总结而来,如果有什么说的不对的地方,还请各位看官指出,我还进行改正

正文

JDK,JRE,JVM三者之间的关系

JDK包含JRE,JRE包含JVM

内存溢出诊断

通过一个 VM argument进行设置 -xx: +HeapDumpOutOfMemoryError

这个命令会导出一个分析文件,需要下载一些工具对这个文件加以分析。

还可以通过JDK自带的可视化工具 console.exe 进行监控。

JVM分类

JAVA虚拟机内存管理

java虚拟机在执行程序的时候会把它所管理的区域划分成不同的数据区。

内存区域可以分为两个部分:

1.线程共享区

2.线程独占区

内存区域之程序计数器

是一块较小的内存空间,是一个当前线程所执行的字节码的行号指示器
字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
如果执行的是线程的java方法,计时器记录的是虚拟机字节码的指令地址,
如果执行的是native方法,那么这个计数器的值是空的(Undefined)
那么另一个问题:为什么需要用程序计数器保存执行的行号呢,是为了线程上下文切换,保证了线程不会错乱,线程只是执行操作,而并不会保存数据。

内存区域之虚拟机栈

描述的Java方法运行的内存模型

每一个方法的调用到完成都对应着栈帧在虚拟机栈中入栈和出栈的过程。

栈的区域是固定的,当我们不断调用方法,就会不断产生栈帧进入栈中,如果超出了栈的大小,就会出现stackOverflow的异常,想象平常最容易出现的场景就是递归,如果没写好的话,无止境的递归。

内存区域之本地方法栈

本地方法栈为虚拟机执行native方法服务

而虚拟机栈为虚拟机执行java方法服务

这就是二者唯一区别的区别,在***hot spot VM中这两个区域并没有明显的区分。
之所以开辟这个区域,是为了方便和系统交互,使用java和操作系统交互,有不便之处,所以最顶层的ClassLoader采用的C++编写。

内存区域之堆

内存中最大的一块。

存放对象的实例。

垃圾收集器管理的主要区域,所以很多人称之为GC堆

如果堆内存溢出,会产生OutOfMemeory的Error

-Xmx -Xms, 这两个VM参数,可以修改堆大小

内存区域之方法区

很多人称之为永生代

垃圾收集在这个区域比较少见。

存储虚拟机加载的类信息(类的版本,字段,方法,接口),常量,静态变量,即时编译器(JIT)编译后的代码等数据。

可能出现OutOfMemory

运行时常量池

属于方法区的一部分

存放编译时生成的字面量,以及符号引用

小例子:

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");

在这里 a与b的地址是相同的,这收益于常量池,而c与a,b是不相同的因为new是直接在堆中开辟了一条内存空间,不受常量池影响的

直接内存大多时候也被称为堆外内存,自从 JDK 引入 NIO 后,直接内存的使用也越来越普遍。通过 native 方法可以分配堆外内存,通过 DirectByteBuffer 对象来操作。

对象创建

给对象分配内存的方式:

具体使用哪一种方式,是由堆内存是否规整决定的,是否规整是由垃圾回收机制决定的,如果垃圾回收会把区域变得相对完整则使用指针碰撞,如果是零散的,则使用空闲列表。

对象的结构

对象的大小必须是八的整数倍。

对象结构:

对象的访问定位

虚拟机参数

1.-Xms 设置堆的最小值

2.-Xmx 设置堆的最大值

3.-Xss 设置栈容量

垃圾回收

打印GC的详细信息 需要在VM 参数中加入下面两个参数:-verbose:gc -xx:PrintGCDetail

如何判定对象为垃圾对象?

1.引用计数法

在对象中添加一个引用计数器,当有地方引用时+1,当引用失效-1。
但是一般并不使用,因为如果存在引用的相互依赖那么引用计数法将会失效。

2.可达性分析

从GC root 节点,向下搜索,如果一个地址对于GC root对象(包括 虚拟机栈中的局部常量表中的引用的对象,方法区中类静态属性引用的对象,方法区中常量所引用的的对象,本地方法栈中引用的对象),再也没有任何可走的路径,那么将会把在堆中的整个内存都给回首掉。

这里说的最多的字眼就是引用,Java 中一共包括四种引用方法:

大多数情况下,回收的都是堆区,很少收集方法区,那是因为这样做性价比很低。

如果回收方法区的话,主要回收两种:废弃常量,无用的类

回收策略:

垃圾回收器:

不同的垃圾回收器对应不同的使用场景。

垃圾收集器的不断推尘出新,其实就是一个不断缩短垃圾回收时间的过程。

上面有一个概念,容易让人混淆,那就是并发和并行,举个例子,并行就是你去看病,医院有多个看病的医生,而并发就是有多个病人找了同一个医生。

内存分配

内存分配原则:

第四十九节:虚拟机工具

虚拟机工具:

性能调优例子

问题为将用户绩效考核信息处理为一个Excel,但是时不时的不定时间会出现卡顿。

解决思路:

根本原因为把一台tomcat的堆设置的太大,而且用户生成excel的时间比较集中,导致大对象不断的生成,导致老年代告急,所以经常Full GC,产生full gc后所有其他的工作线程被阻塞,所以导致会有时间空档期。

解决方案:在一台服务器上部署多个服务器构成集群,每个集群的堆分配4G。

后记

在今后的不断学习中,我会不断的更新这篇文章。

上一篇 下一篇

猜你喜欢

热点阅读