1、JAVA内存区域与内存溢出

1.1、概述

Java中JVM提供了内存管理机制,Java虚拟机在执行Java程序的过程中会把内分分为不同的数据区,如图:

1.2、程序计数器

程序计数器是当前线程所执行的字节码的行号指示器,作用就是根据计数器的值获取下一条要执行的字节码指令。当执行的是java方法,则记录的是正在执行的虚拟机字节码指令的地址,如果是Native方法,则这个计数器的值为空。不存在任务OutOfMemoryError。

1.3、虚拟机栈

每个普通Java方法(除去Native方法)在执行的时候都会同时创建栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息,每个方法被调用直到完成的过程对应着栈帧在JVM栈中的入栈与出栈。其中局部变量表所需要的内存空间在编译器间完成分配。

跟虚拟机栈相关联的异常有两种:

  • StackOverflowError

线程请求的栈深度大于虚拟机允许的最大深度。

  • OutOfMemoryError

虚拟机栈扩展时无法申请到足够的内存。

1.4、本地方法栈

用于虚拟机执行Native方法,其他和本地方法栈相同。也会有StackOverflowError和OutOfMemoryError。

1.5、堆

虚拟机启动后创建堆,用于存放对象实例。堆时垃圾回收器的主要工作区域,主要分为新生代和老年代,新生代又可以细分为Eden空间、From Survivor空间、To Survivor空间。java程序启动时,可用-Xmx与-Xms控制堆的大小。如果堆中没有内存完成实例分配并且堆也无法扩展时会抛出OutOfMemoryError。

1.6、方法区

方法区主要存储类的元数据,如虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码,JDK1.8之前以永久代实现,JDK1.8之后使用元空间,而且元空间使用的是系统内存。如果无法申请内存时,会抛出OutOfMemoryError。

2、垃圾回收

2.1、如何判断对象已经死亡?

2.1.1、引用计数法

在对象中添加一个引用计数器,当有个地方引用时,计数器值 1,当引用失效时,计数器值-1。计数器为0的对象就是死亡的,但是这里有个问题:对象循环引用,两个对象互相引用着对方,导致它们的引用计数器不为0,于是无法通知GC回收。

2.1.2、GC Roots搜索

Java中采用的是GC ROOT搜索,思路就是通过一系列名为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索中所走过的路径称为引用链,当GC Roots对某一对象不可达时,则证明此对象不可用。

GC Roots包括以下几种:

  • 栈帧中的本地变量表中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈Native方法引用的对象

2.2、垃圾收集算法

2.2.1、标记-清除算法

标记-清除算法分为两个阶段:

  • 标记:首先标记出所有需要回收的对象。
  • 清除:统一回收被标记的对象。

这个算法有连个缺点:

  1. 效率不高
  2. 会产生不连续的内存碎片
2.2.2、复制算法

复制算法的效率很高,其将可用内存按照容量划分为大小相等的两块,每次只使用其中的一块,当一块用完时,就将还存活的对象复制到另一块上面,然后清除掉使用过的内存空间。

这种算法很适合回收新生代,在新生代中分为Eden空间、From Survivor空间、To Survivor空间,一般分配的内存比例为8:1:1,当回收时,将Eden与From Survivor中还存活的对象一次性拷贝到To Survivor中,之后清理掉Eden与From Servivor空间,当To Survivor空间不够时,需要依赖老年代。

2.2.3、标记-整理算法

在老年代,对象的存活率比较高,所以标记-整理算法被提出来了,首先标记出要回收的对象,然后将所有存活的对象都向一端移动,然后直接清理掉死亡的对象:

2.2.4、分代收集算法

分代回收的思想就是根据对象的存活周期,将不同的内存划分为几块,根据每块内存的特点采用适当的收集算法,比如新生代采用复制算法,老年代采用标记-整理算法。

2.3、垃圾收集器

下图展示了7种不同分代的收集器,如果两个收集器之间存在连线,则表示可以搭配使用。

通过以下命令可以查看垃圾回收器信息:

java -XX: PrintCommandLineFlags -version

我的测试服务器结果:

-XX:InitialHeapSize=524503488 -XX:MaxHeapSize=8392055808 -XX: PrintCommandLineFlags -XX: UseCompressedClassPointers -XX: UseCompressedOops -XX: UseParallelGC
java version "1.8.0_152"
Java(TM) SE Runtime Environment (build 1.8.0_152-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.152-b16, mixed mode)

可以看到使用的是:ParallelGC。

JVM参数对应关系:

下面简单介绍7中垃圾回收器:

2.3.1、Serial收集器

新生代单线程收集器,简单高效。

2.3.2、ParNew收集器

Serial收集器的多线程版本,除了在垃圾回收时使用多线程,其余都和Serial收集器相同。

2.3.3、Parallel Scavenge收集器

Parallel Scavenge收集器是并行的采用复制算法的新生代收集器,着重于系统的吞吐量,适合后台运算而不需要太多用户交互的任务。

2.3.4、Serial Old收集器

Serial Old是单线程的老年代垃圾收集器,使用标记-整理算法。具有简单高效的特点。

2.3.5、Parallel Old收集器

Parallel Old收集器是Parallel Scanenge的老年代版本,多线程垃圾回收,也是用标记-整理算法。

2.3.6、CMS收集器

CMS注重服务的响应时间,是基于标记-清除算法实现。具有并发收集、低停顿的特点。

2.3.7、G1收集器

Garbage First,基于标记-整理算法,其将整个Java堆(包括新生代和老年代)划分为多个大小固定的独立区域,并且跟踪这些区域里的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域。

3、CPU占用过高问题排查

3.1、 linux查看进程信息

top

3.2、查看进程占用cpu最多的线程

ps -mp 23967 -o THREAD,tid,time

3.3、线程ID转16进制

printf "%x\n" 23968

3.4、查看线程信息

jstack  23967  |grep -A  10  5da0

jstack 23967  |grep 5da0 -A 30

3.5、 查看进程的对象信息

jmap -histo:live 23967 | more

3.6、查看进程的GC情况

jstat -gcutil 23967 1000 100

参考

利用jmap和MAT等工具查看JVM运行时堆内存

JVM内存区域与垃圾回收的更多相关文章

  1. 浅析JVM内存区域及垃圾回收

    一.JVM简介 JVM,全称Java Virtual Machine,即Java虚拟机.以Java作为编程语言所编写的应用程序都是运行在JVM上的.JVM是一种用于计算设备的规范,它是一个虚构出来的计 ...

  2. Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收

    很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...

  3. JVM内存管理及垃圾回收【转】

    很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...

  4. JVM内存管理和垃圾回收机制介绍

    http://backend.blog.163.com/blog/static/20229412620128233285220/     内存管理和垃圾回收机制是JVM最核心的两个组成部分,对其内部实 ...

  5. 浅谈JVM内存分配与垃圾回收

    大家好,我是微尘,最近又去翻了周志明老师的<深入理解Java虚拟机>这本书.已经看了很多遍了,每次都感觉似乎看懂了,但没过多久就忘了.这次翻了第三章的垃圾收集器与内存分配策略,感觉有了新的 ...

  6. JVM内存分配与垃圾回收机制管理

    项目上线,性能优化有个重要组成就是jvm内存分配和垃圾回收机制的管理配置. 网上随便能搜到相关的具体步骤,以及内存中各种参数对应的意义,不再赘述. 干货就是直接抛出遇到的问题,以及如何解决的,再说说待 ...

  7. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  8. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...

  9. JVM内存管理及垃圾回收

    一.JVM内存的构 Java虚拟机会将内存分为几个不同的管理区,这些区域各自有各自的用途,根据不同的特点,承担不同的任务以及在垃圾回收时运用不同的算法.总体分为下面几个部分: 程序计数器(Progra ...

随机推荐

  1. Mybais面试题(一)

    1.对于Hibernate和MyBatis的区别与利弊,谈谈你的看法   Hibernate与MyBatis的对比:   1.MyBatis非常简单易学,与Hibernate相对较复杂,门槛较高;   ...

  2. (转)Qt添加windows开机自启动

    原博文地址为:https://blog.csdn.net/x356982611/article/details/53183144 简介 window下开机启动最简单的实现方式就是在注册表中添加启动项目 ...

  3. NuGet Package Explorer 中文版

    Id:NuGet Package Explorer 中文版 Description:基于原版 5.7.170 的绿色中文版,无任何‘添加剂’ Version:5.7.170 Download:Gith ...

  4. 关于css布局中,inline-block元素间隙的处理方法

    关于inline-block元素间隙的处理 参考橱窗外的小孩,原文链接https://www.cnblogs.com/showcase/p/10469361.html 如下,两个inline-bloc ...

  5. Java中的引用与ThreadLocal

    Java中的引用--强软弱虚 强引用 Object object = new Object(),这个object就是一个强引用.如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回 ...

  6. C#LeetCode刷题-字典树

    字典树篇 # 题名 刷题 通过率 难度 208 实现 Trie (前缀树)   48.6% 中等 211 添加与搜索单词 - 数据结构设计   39.9% 中等 212 单词搜索 II   27.9% ...

  7. C#设计模式之10-外观模式

    外观模式(Facade Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/407 访问. 外观模式属于结构 ...

  8. Who Am I? Personality Detection based on Deep Learning for Texts 阅读笔记

    文章目录 源代码github地址 摘要 2CLSTM 过程 1. 词嵌入 2. 2LSTM处理 3. CNN学习LSGCNN学习LSG 4. Softmax分类 源代码github地址 https:/ ...

  9. Android 开发学习进程0.15 adb cardview framelayout 控件设置状态获取焦点

    Android设备调试桥 即adb 使用adb进行无线调试的一些常用命令 adb tcpip 5555 设置调试端口为5555 防止冲突 adb shell ifconfig wlan0 查询局域网中 ...

  10. python库安装失败的解决方法

    安装python库 在https://www.lfd.uci.edu/~gohlke/pythonlibs 中,搜索对应库名称 选取对应版本下载 在cmd窗口中,用命令 pip install+文件路 ...