读Java性能权威指南(第2版)笔记11_堆内存上
2023-04-18 15:26:35 时间
1. 通用规则
1.1. 不要假设问题出在堆空间
1.2. 谨慎地创建对象并尽快丢弃它们
1.3. 使用更少的内存是提高垃圾回收器效率最好的办法
1.3.1. 减少内存使用是一个重要的目标
1.3.2. 和大多数性能优化主题一样,将精力集中于最大化利用现有内存会更有帮助
1.4. 对象重用方式
1.4.1. 线程局部变量
1.4.2. 特殊对象引用
1.4.3. 对象池
1.5. 重用对象意味着它们将长期存在并会影响垃圾回收器
1.5.1. 当它们被合理地重用时,整体性能将得到提升
2. 堆直方图
2.1. heap histogram
2.2. 快速查看应用程序中对象数量的方法,不需要生成完整堆转储
2.3. 用于识别由于某种特定类型的对象创建得太多而导致的内存问题
2.4. % jmap -histo process_id
2.5. % jmap -histo:live process_id
3. 堆转储
3.1. heap dump
3.2. 最强大的跟踪内存使用的技术
3.3. 常用工具
3.3.1. jvisualvm
3.3.1.1. 从正在运行的程序中获得堆转储文件
3.3.1.2. 可以打开之前生成的堆转储文件
3.3.1.3. 检查最大的保留对象并执行对堆的任意查询
3.3.2. 开源的Eclipse Memory Analyzer Tool
3.3.2.1. mat
3.3.2.2. 加载一个或者多个堆转储文件并对其进行分析
3.3.2.3. 可以产生报告
3.3.2.4. 可以用来浏览堆
3.3.2.5. 对堆执行类似SQL的查询
3.3.2.6. 提示可能出现问题的地方
3.4. % jcmd process_id GC.heap_dump /path/to/heap_dump.hprof
3.5. % jmap -dump:live,file=/path/to/heap_dump.hprof process_id
3.5.1. 包含live选项会在堆被转储之前强制执行Full GC
3.5.2. 如果因为某些原因你想包含其他的对象(死对象),可以在jcmd命令行的末尾加上-all
4. 内存分析
4.1. 对象的浅大小(shallow size)
4.1.1. 对象本身的大小
4.2. 对象的深大小(deep size)
4.2.1. 包含它所引用的对象的大小
4.3. 对象的深大小和保留大小的区别在于其引用的对象是否是共享的
4.4. 保留大量堆空间的对象通常被称为堆的支配者
4.5. 一般的经验法则是,寻找路径应该从集合对象(如HashMap)而不是从条目(如HashMap$Entry)开始,并且要寻找最大的集合
5. 内存溢出错误
5.1. out-of-memory
5.2. JVM没有可用的原生内存
5.2.1. 在Linux中,用户常常只被允许创建1024个进程
5.2.1.1. 可以通过运行ulimit-u来检查这个值
5.2.1.2. 试图创建第1025个线程,JVM就会抛出OutOfMemoryError异常
5.2.1.3. 操作系统对进程数量施加的限制导致的错误
5.2.2. 错误消息
5.2.2.1. Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread
5.3. 元空间内存不足
5.3.1. 这个错误的发生通常是因为你设置了最大大小
5.3.1.1. 元空间默认情况下没有最大大小的限制
5.3.2. 根本原因
5.3.2.1. 分配的元空间已经放不下应用程序使用的类
5.3.2.2. 涉及类加载器的内存泄漏
5.3.2.2.1. 最常发生在动态加载类的服务器中
5.3.2.2.1.1. 增加元空间的大小会有帮助,但也只是推迟了错误发生的时间而已
5.3.2.2.1.2. 除了联系应用服务器厂商让他们修复内存泄漏问题之外,没有其他办法
5.3.3. 错误消息
5.3.3.1. Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
5.4. Java堆本身内存不足
5.4.1. 对于给定大小的堆,应用程序已经无法创建任何额外的对象
5.4.2. 错误消息
5.4.2.1. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
5.5. -XX:+HeapDumpOnOutOfMemoryError
5.5.1. 打开这个标志会让JVM在抛出内存溢出错误时创建堆转储
5.5.2. 默认是false
5.6. -XX:HeapDumpPath=
5.6.1. 该标志指定堆转储的写入位置
5.6.1.1. 可以指定目录
5.6.1.1.1. 会使用默认文件名
5.6.1.2. 可以指定要生成的实际文件名
5.6.2. 默认位置是应用程序当前工作目录下的java_pid.hprof
5.7. -XX:+HeapDumpAfterFullGC
5.7.1. 运行Full GC之后生成堆转储
5.8. -XX:+HeapDumpBeforeFullGC
5.8.1. 运行Full GC之前生成堆转储
5.9. -XX:+ExitOnOutOfMemoryError
5.9.1. JVM在堆内存用尽时退出
5.9.2. 默认是false
5.10. JVM花费了太多时间执行GC
5.10.1. 错误消息
5.10.1.1. Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
5.11. -XX:GCTimeLimit=N
5.11.1. 在Full GC中花费的时间超过了指定值
5.11.2. 默认值是98
5.11.2.1. 98%的时间花在GC上,该条件就满足
5.12. -XX:GCHeapFreeLimit=N
5.12.1. 一次Full GC回收的内存量小于指定值
5.12.2. 默认值是2
5.12.2.1. Full GC期间回收的内存小于堆的2%,该条件就满足
5.13. -XX:+UseGCOverheadLimit
5.13.1. 前面两个条件在5个连续的Full GC周期中都成立
5.13.2. 默认值true
相关文章
- Jease 2.6发布 Java开源内容框架
- JVM调优总结:反思
- JVM调优总结:调优方法
- JVM调优总结:新一代的垃圾回收算法
- JVM调优总结:典型配置举例
- JVM调优总结:分代垃圾回收详述
- JVM调优总结:垃圾回收面临的问题
- JVM调优总结:基本垃圾回收算法
- JVM调优总结:一些概念
- 用Java GUI编写的画板程序
- Java的动态绑定机制
- jOOQ 2.0.2发布 Java的ORM框架
- Java中带复选框的树的实现和应用
- Java网络编程菜鸟进阶:TCP和套接字入门
- 甲骨文与谷歌专利权之争定于今年三月开审
- Java调用C/C++编写的第三方dll动态链接库
- 集成开发环境 NetBeans IDE 7.1正式版发布
- kangle 2.7.5紧急发布 防hash碰撞攻击
- 东方通技术引领模式为国产软件“争权”
- UML中关联,组合与聚合等关系的辨析