深入理解Java虚拟机(六)——JVM调优分析与实战
大内存硬件上的程序部署策略
单个虚拟机管理大内存
出现问题
如果JVM中的堆内存太小,就会频繁地出发GC,而每次GC会将用户线程暂停,所以,频繁地GC会导致长时间的停顿。如果扩大计算的内存的大小,就能降低GC触发的频率。
32位系统最大支持4g内存,而64位操作系统可以最大支持128g内存,所以,我们可以通过换用64位系统和提高内存的方式降低虚拟机的用户线程停顿,但是还是有问题。
虽然Full GC总体的频率降低了,但是每次Full GC的时间却增长了,因为积攒的需要回收的空间变大了嘛。这样会导致长时间的停顿,比以往更要命。
解决方案
对于大内存的硬件,一定要控制Full GC的频率就能减少长时间的停顿,比如一天都不出现一次Full GC,可以在深夜没有用户使用的时候进行一次。
控制Full GC频率的关键是老年代的相对稳定,如何控制老年代稳定:
- 保证绝大多数对象是朝生夕灭的,大多数对象的生存时间不能太长,尤其是大对象。
- 提高大对象进入老年代的门槛,这样可以让对象先在新生代被Minor GC掉。
调整为建立5个32位JDK的逻辑集群,每个进程按2GB内存计算(其中堆固定为1.5GB),占用了10GB内存。另外建立一个Apache服务作为前端均衡代理作为访问门户。考虑到用户对响应速度比较关心,并且文档服务的主要压力集中在磁盘和内存访问,处理器资源敏感度较低,因此改为CMS收集器进行垃圾回收。部署方式调整后,服务再没有出现长时间停顿,速度比起硬件升级前有较大提升。
单个虚拟机管理大内存的问题
- 回收大内存耗时长,G1出现后才有所改善。
- 64位虚拟机性能低于32位的。
- 法在堆内存溢出的时候,如果,堆过大就无法产生堆转存储快照,转了也很难分析,太大了
- 64位虚拟机内存消耗过大,因为指针膨胀、数据对齐。
一台物理机上建立虚拟机逻辑集群管理内存
同时使用若干个虚拟机建立逻辑集群来利用硬件资源。做法是在一台物理机器上启动多个应用服务器进程,为每个服务器进程分配不同端口,然后在前端搭建一个负载均衡器,以反向代理的方式来分配访问请求。
存在问题
- 磁盘竞争,多个节点同时访问一个磁盘文件,导致IO异常。
- 很难高效利用资源池。可能一个还有很多,另一个已经满了。
- 如果使用32位系统,内存空间太小。
- 造成内存的浪费,可以把本地缓存改为集中式缓存。
直接内存的溢出
问题描述
服务端不定时抛出内存溢出异常,将堆内存调到最大,还是有这个问题。加入-XX:+HeapDumpOnOutOfMemoryError参数,居然也没有任何反应,再用jstat查看GC堆,也很正常。说明不是堆内存溢出。系统的内存是2g,而1.6g分给了Java堆,直接内存只剩下0.4g。如果使用了NIO,那么JVM会在JVM内存之外分配内存空间,这部分内存也叫“直接内存”。因此,如果程序中使用了NIO,那么就要小心所以是直接内存异常。
直接内存的回收
虚拟机对直接内存不能像Java堆那样,发现空间不足就触发GC,而是在老年代满了之后的Full GC顺便清理直接内存。所以,会出现直接内存溢出。
虚拟机进程崩溃
异步请求
web服务器采用HTTP通信,而HTTP基于TCP。异步通信就是当客户端向服务器发送一个HTTP请求后,将这个请求的TCP连接委托给其他线程,自己去做其他的事情,那个被委托的线程就等你这服务器的反馈。当这个线程接收到了反馈,就将数据转交给刚才的线程,这就是异步通信。
异步请求导致进程奔溃
使用了异步方式调用web服务,由于两边的服务速度完全不对等,时间长了就会累计越来越多的服务请求,从而导致等到的线程和socket连接越来越多,就会超过虚拟机的承受能力,就会崩溃。
解决方法
将异步调用改成生产者消费折模式的消息队列。
大量大对象进入堆
问题描述
一下子有太多太大的对象进入新生代,而暂时又不能被回收,由于新生代中采用的标记复制算法,这样导致Minor GC的效率低,同时会很快占满新生代,频繁触发GC,从而导致停顿。
解决方法
修改进入老年代的年龄限制,让对象马上进入老年代。
本质问题还是要减少大对象,提高空间利用效率。
这个案例中由于使用了HashMap 作为长整型的数据存储结构,这样的空间使用效率非常低。
安全点导致的长时间停顿
问题描述
当个别线程没有进入安全点,而其他线程都都在安全等待的时候,就会导致长时间的停顿。
当线程在一个循环中,可能需要等待循环全部跑完才能进入安全点,这样其他线程也必须一起等着。
解决方法
把循环索引中的数据类型从int改为long。
处理大对象
大对象对于虚拟机是一个非常棘手的问题。可能会导致频繁的GC,占用大量空间,延长GC的时间。
处理方法
- 避免大对象的产生:选择空间效率较高的数据结构存储大的信息。
- 缩短大对象的生存时间:尽快丢掉大对象,这样就能避免对象占用空间,多次被复制所消耗的时间。
深入理解Java虚拟机(六)——JVM调优分析与实战的更多相关文章
- java虚拟机学习-JVM调优总结-分代垃圾回收详述(9)
为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大量的对象, ...
- java虚拟机学习-JVM调优总结-调优方法(12)
JVM调优工具 Jconsole,jProfile,VisualVM Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪.详细说明参考这里 ...
- 【java虚拟机】jvm调优原则
转自:https://www.cnblogs.com/xiaopaipai/p/10522794.html 合理规划jvm性能调优 JVM性能调优涉及到方方面面的取舍,往往是牵一发而动全身,需要全盘考 ...
- java虚拟机学习-JVM调优总结-新一代的垃圾回收算法(11)
垃圾回收的瓶颈 传统分代垃圾回收方式,已经在一定程度上把垃圾回收给应用带来的负担降到了最小,把应用的吞吐量推到了一个极限.但是他无法解决的一个问题,就是Full GC所带来的应用暂停.在一些对实时性要 ...
- java虚拟机学习-JVM调优总结-典型配置举例(10)
以下配置主要针对分代垃圾回收算法而言. 堆大小设置 年轻代的设置很关键 JVM中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理 ...
- java虚拟机学习-JVM调优总结(5)
数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型.基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对象本身, ...
- 【java虚拟机】jvm调优
转自:https://www.cnblogs.com/starhu/p/6400348.html?utm_source=itdadao&utm_medium=referral 堆大小设置JVM ...
- java虚拟机学习-JVM调优总结(6)
1.Java对象的大小 基本数据的类型的大小是固定的,这里就不多说了.对于非基本类型的Java对象,其大小就值得商榷. 在Java中,一个空Object对象的大小是8byte,这个大小只是保存堆中一个 ...
- java虚拟机学习-JVM调优总结-垃圾回收面临的问题(8)
如何区分垃圾 上面说到的“引用计数”法,通过统计控制生成对象和删除对象时的引用数来判断.垃圾回收程序收集计数为0的对象即可.但是这种方法无法解决循环引用.所以,后来实现的垃圾判断算法中,都是从程序运行 ...
随机推荐
- openwrt——preinit.sh学习
boot_hook_init() { local hook="${1}_hook" export -n "PI_STACK_LIST=${PI_STACK_LIST:+$ ...
- 从头学起Verilog(二):时序逻辑基础与回顾
引言 时序逻辑对于数字电路设计十分重要,本文针对数字电路中的时序逻辑部分进行了系统的回顾. 存储器件 由于时序逻辑的输出不但受当前输入影响,还受之前的输入的影响,所以需要有存储单元对以前的输入进行存储 ...
- transformer多头注意力的不同框架实现(tensorflow+pytorch)
多头注意力可以用以下一张图描述: 1.使用pytorch自带的库的实现 torch.nn.MultiheadAttention(embed_dim, num_heads, dropout=0.0, b ...
- cgroup实践-资源控制
1.Cgroup安装 安装Cgroups需要libcap-devel和libcgroup两个相关的包 yum install gcc libcap-devel 2.Cgroup挂载配置 Cgroup对 ...
- python之对元组的初步了解
元组: 元组与列表类似但是又有不同,主要的不同就是元组属于不可变序列,一旦创建,任何方法都不可以修改元素. 元组使用小括号( )表示,这与列表不一样,列表是用方括号表示[ ]. a=('a','b') ...
- Linux-CentOS7下安装Oracle11g
简述: 本文操作环境采用CentOS7 Linux安装Oracle11g与Windows区别较大,在Linux下需要创建用户以及用户组来供Oracle使用 Windows可以直接图形化界面从第一步到最 ...
- hashmap(有空可以看看算法这本书中对于这部分的实现,很有道理)
//转载:https://baijiahao.baidu.com/s?id=1618550070727689060&wfr=spider&for=pc 1.为什么用HashMap? H ...
- CF1156D 0-1-Tree
路径考虑顺序. 显然合法的路径只有以下两种: 一段 \(0\) 加一段 \(1\) 或一段 \(1\) 加一段 \(0\). 全 \(0\) 或全 \(1\). 用并查集将边权为 \(0\) 和 \( ...
- 编程C语言进阶篇——自定义数据类型:结构体
一.结构体 定义方法: 结构名 变量名 特点: 两个同类型的结构变量可以相互赋值,但是结构变量之间不能使用"<","=="等运算符,如果使用则需要对运算符 ...
- redis-cli 持久化,复制,哨兵,事务,流水线
一.持久化: 快照文件RDB 保存"开始"创建新快照一刻的内存快照,创建过程的内存变化不会被记录 创建快照的办法有几种 1.客户端可以通过想Redis发送BGSAVE来创建一个快照 ...