没有合适的资源?快使用搜索试试~ 我知道了~
JVM8全方位理解、实现linux下和window下对jar、idea、tomcat等应用程序的jvm的实战操作
资源详情
资源评论
资源推荐
JVM 调优实战全方面总结
一:JVM 的结构
Java 堆重点理解
Java 栈重点理解
永久代 去除永久代了解替代品
本地方法栈 部分代码区域无需了解
C Heap非 区域的内存使用无需了解
二:JVM 的了解
一般一个 应用程序会启动一个 实例,每个 实例之间彼此独立。
但是常见的情况是运行多个 应用程序的单个应用程序服务器(如 等)
此时多个 应用程序就共享一个 但是每个应用程序在各自的类加载器中
实现逻辑上彼此分开减少了意外进程内串扰的可能性。
三:堆与栈的介绍
设计角度区别:
栈:代表了处理逻辑。解决的是程序如何执行或者说如何处理数据。
堆:代表了数据。解决的是数据存储的问题,即数据怎么放,放哪里。
栈和堆的存储:
栈:存储了基本数据类型和堆中对象的引用。一个对象大小是不可估计的或者说是动态变化的,但是这个对象的引
用(地址)只有 。
【 注 】 : 栈 的 大 小 通 过 来 设 置 , 当 栈 中 存 储 数 据 比 较 多 时 , 需 要 适 当 调 大 这 个 值 , 否 则 会 出 现
!"#$%### 异常。
堆:存储的是对象。
栈与堆的关系:
不同的线程执行的逻辑不同,因此在 中一个线程对应有一个栈。
堆相当于一个共享内存,被所有线程共享,是为栈进行数据存储服务的。
四:如何区分堆内存中垃圾
栈是真正进行程序执行地方,所以要获取哪些对象正在被使用,则需要从 栈开始。
除了栈外,还有系统运行时的寄存器等,也是存储程序运行数据的。这样,以栈或寄存器中的引用为起点,我们可
以找到堆中的对象,又从这些对象找到对堆中其他对象的引用,这种引用逐步扩展,最终以 & 引用或者基本类型结束,
这样就形成了一颗以 栈中引用所对应的对象为根节点的一颗对象树。
对象树上的对象,都是当前系统运行所需要的对象,不能被垃圾回收。而其他剩余对象,则可以视为无法被引用到
的对象,可以被当做垃圾进行回收。
五:堆内存中垃圾回收策略(算法)
1.引用计数
原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为 '
的对象。此算法最致命的是无法处理循环引用的问题。
2.标记-清除
第一阶段从引用根节点开始标记所有被引用的对象。
第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。
3.复制
此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在
使用中的对象复制到另外一个区域中。此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去
以后还能进行相应的内存整理,不会出现(碎片)问题。此算法的缺点也是很明显的,就是需要两倍内存空间。
4.标记-整理
此算法结合了(标记清除)和(复制)两个算法的优点。
第一阶段从根节点开始标记所有被引用对象。
第二阶段遍历整个堆,清除未标记对象并且把存活对象(压缩)到堆的其中一块,按顺序排放。此算法避免了(标
记清除)的碎片问题,同时也避免了(复制)算法的空间问题。
5.分代(现在的使用策略--重点)
5.1 年轻代(Young 空间)概念
Eden 区:用于存放使用 或者 * 等方式等所有新生成的对象。
若这个对象太大,或者超过了设定的额
2 个 Surivor 区:一般称为 !' 和 !+,理论上一样大,没有区别。用于存储临时对象,交换空间的作用。
5.2 年老代(Old 空间)概念
在年轻代中经历了 , 次垃圾回收后仍然存活的对象,就会被放到年老代中。
5.3 持久代(Permanent 空间)概念(jdk8 取消了只需关注 Metaspace)
用于存放静态文件,如今 类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者
调用一些 ,例如 -.# 等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。
持久代大小通过/01#!.23进行设置。
从 +4 开始就从持久代移除, 发布彻底废除了它,持久代的继承者:
56-! 现在使用的时本地内存来存储类元数据,被称为 。
0!.2 来设置类元数据的本地内存大小,如果没有指定这个标记, 会根据运行时应用程序
需求来动态控制的大小。
5.4 实现原理
+ 在不断创建对象过程中 % 满时,这时会进行第一次 7(也叫 .#7),此时会把 % 区中存活的对
象放在 !' 或者 !+ 其中一个区(假设 !'),若满了则放到 " 空间。之后将 % 区进行清空。
8 当第二次 % 满时,会将 % 区与 !' 区活着的对象放在 !+ 区,若满了则放到 " 空间,之后对 % 和
!' 区进行清空。
9 依次类推,反反复复多次(默认 +: 次)没有被淘汰的对象就放到 " 区。
5.5 垃圾回收触发条件
1. Minor GC
一般情况下,当新对象生成,并且在 % 申请空间失败时,就会触发 .#7,对 % 区域进行 7,清
除非存活对象,并且把尚且存活的对象移动到 !&#.# 区。然后整理 !&#.# 的两个区。这种方式的 7 是对年
轻代的 % 区进行,不会影响到年老代。因为大部分对象都是从 % 区开始的,同时 % 区不会分配的很大,
所以 % 区的 7 会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使 % 去能尽快空闲出来。
2. Full GC
对整个堆进行整理,包括 ;& 、" 和 1#。<&7 因为需要对整个对进行回收,所以比 .#7 要慢,
因此应该尽可能减少 <&7 的次数。在对 调优的过程中,很大一部分工作就是对于 <&7 的调节。
有如下原因可能导致 <&7:
年老代(=&#)被写满
! 被显示调用
上一次 7 之后 - 的各域分配策略动态变化
5.6 回收器选择
1. 串行回收器(Serial)
串行回收器是最简单的一个,你都不会考虑使用它,因为它主要是面向单线程环境的(比如说 98 位的
>.)以及比较小的堆。这个回收器工作的时候会将所有应用线程全部冻结,就这一点而言就使得它完全
不可能会被服务端应用所采用。
如何使用它:你可以打开/?@!#.7 这个 参数来使用它。
2. 并行回收器(Parallel)
将串行回收多线程化,垃圾回收时,应用程序暂停,由于多线程回收,在多核 1@ 上,回收效率会高于串
行回收器,反之在单核 1@ 上效率不如串行回收器。这是 的默认回收器。正如它的名字所说的那样,它的
最大的优点就是它使用多个线程来扫描及压缩堆。它的缺点就是不管执行的是 .#7 还是 A&7 它都会暂停
应用线程。并行回收器最适合那些可以容许暂停的应用,它试图减少由回收器所引起的 1@ 开销。
3. 并发回收器(CMS=concurrent-mark-sweep)
这个算法使用了多个线程(&##)来扫描堆并标记(#)那些不再使用的可以回收的对象。
这个算法在两种情况下会进入一个)B#)的模式:当进行根对象的初始标记的时候(老生代中线程入
口点或静态变量可达的那些对象)以及当这个算法在并发运行的时候应用程序改变了堆的状态使得它不得不回
去再次确认自己标记的对象都是正确的。
使用这个回收器最大的问题就是会碰到 #CA.&#,这是指在回收新生代及年老代时出现了竞争条件
的情况。如果回收器需要将年轻的对象提升到年老代中,而这个时候年老代没有多余的空间了,它就只能先进
行一次 !=>!=B>#的 A&7 了DD这种情况正是 ! 所希望避免的。为了确保这种情况不会发生,你
要么就是增加老生代的大小(或者增加整个堆的大小),要么就是给回收器分配一些后台线程以便与对象分配
的速度进行赛跑。
这个算法的另一个缺点就是和并行回收器相比,它使用的 1@ 资源会更多,它使用了多个线程来执行扫描
和回收,这样才能让应用持续提供更高级别的吞吐量。对于大多数长期运行的程序而言,应用的暂停对它们是
很不利的,这个时候可以考虑使用 ! 回收器。尽管如此,这个算法也不是默认开启的。你得指定 /
?@#!7 来启用它。假设你的堆小于 7,而你又希望分配更多的 1@ 资源以避免应用暂停,那么
这就是你要选择的回收器。然而,如果堆大于 7 的话,你可能更希望使用最后的这个DD7+ 回收器。
4. 分代垃圾回收器(G1)
7+(7# E#)回收器在 654& 中首次引入,它的设计目标是能更好地支持大于 7F 的堆。7+
回收器将堆分为多个区域,大小从 +F 到 98F 不等,并使用多个后台线程来扫描它们。7+ 回收器会优先扫描
那些包含垃圾最多的区域,这正是它的名字的由来( 7# E#)。这个回收器可以通过/@7+7 标记来
启用。
这一策略减少了后台线程还未扫描完无用对象前堆就已经用光的可能性,而那种情况回收器就必须得暂停
应用,这就会导致 !=> 回收。7+ 的另一个好处就是它总是会进行堆的压缩,而 ! 回收器只有在 A&7 的时
候才会干这事。
过去几年里,大堆一直都是一个充满争议的领域,很多开发人员从单机器单 模型转向了单机器多
的微服务,组件化的架构。这是许多因素所驱动的,包括隔离程序的组件,简化部署,避免重新加载应用类到
内存所产生的开销( 中这点已经得到了改善)。
尽管如此,这么做最主要还是希望能避免大堆的 7 中长时期的)B#)的暂停(在一次大的回收中
需要花费数秒才能完成)。像 6# 这样的容器技术也加速了这一进程,它们使得你可以很轻松地在同一台物
理机上部署多个应用。&8' 所引入的一个很棒的优化就是 7+ 回收器中的 字符串去重(!#.
&.C)。由于字符串包括它们内部的 B#GH数组)占用了大多数的堆空间,这项新的优化旨在使得 7+
回收器能识别出堆中那些重复出现的字符串并将它们指向同一个内部的 B#GH数组,以避免同一个字符串的多份
拷贝,那样堆的使用效率会变得很低。你可以使用/?@!#. 6&.C 这个 参数来试一下这个特性。
剩余12页未读,继续阅读
不死就是干
- 粉丝: 2
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0