内存溢出

内存溢出的原因:程序在申请内存时,没有足够的内存空间

栈溢出

方法死循环递归调用(StackOverflowError)、不断建立线程(OutOfMemoryError)

堆溢出

不断创建对象,分配对象大于最大堆的大小(OutOfMemoryError)

直接内存

JVM 分配的本地直接内存大小大于 JVM 的限制(可以通过-XX:MaxDirectMemorySize 来设置(不设置的话默认与堆内存最大值一样,也会出现

OOM 异常)

方法区溢出

在经常动态生产大量 Class 的应用中,CGLIb 字节码增强,动态语言,大量 JSP(JSP 第一次运行需要编译成 Java 类),基于 OSGi 的应用(同一个类,被不同的加载器加载也会设为不同的类)

内存泄漏

程序在申请内存后,无法释放已申请的内存空间。

长生命周期的对象持有短生命周期对象的引用

例如将 ArrayList 设置为静态变量,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏

连接未关闭

如数据库连接、网络连接和 IO连接等,只有连接被关闭后,垃圾回收器才会回收对应的对象。

变量作用域不合理

例如,1.一个变量的定义的作用范围大于其使用范围,2.如果没有及时地把对象设置为 null

内部类持有外部类

Java的非静态内部类的这种创建方式,会隐式地持有外部类的引用,而且默认情况下这个引用是强引用,因此,如果内部类的生命周期长于外部类的生命周期,程序很容易就产生内存泄漏
如果内部类的生命周期长于外部类的生命周期,程序很容易就产生内存泄漏(你认为垃圾回收器会回收掉外部类的实例,但由于内部类持有外部类的引用,导致垃圾回收器不能正常工作)
解决方法:你可以在内部类的内部显示持有一个外部类的软引用(或弱引用),并通过构造方法的方式传递进来,在内部类的使用过程中,先判断一下外部类是否被回收;

Hash 值改变

在集合中,如果修改了对象中的那些参与计算哈希值的字段,会导致无法从集合中单独删除当前对象,造成内存泄露(有代码案例 Node 类)

内存泄漏和内存溢出辨析

内存溢出:实实在在的内存空间不足导致;
内存泄漏:该释放的对象没有释放,常见于使用容器保存元素的情况下。
如何避免:
内存溢出:检查代码以及设置足够的空间
内存泄漏:一定是代码有问题

往往很多情况下,内存溢出往往是内存泄漏造成的。

了解 MAT

浅堆和深堆

浅堆 :(Shallow Heap)是指一个对象所消耗的内存。例如,在 32 位系统中,一个对象引用会占据 4 个字节,一个 int 类型会占据 4 个字节,long 型变量会占据 8 个字节,每个对象头需要占用 8 个字节。
深堆 :这个对象被 GC 回收后,可以真实释放的内存大小,也就是只能通过对象被直接或间接访问到的所有对象的集合。通俗地说,就是指仅被对象所持有的对象的集合。深堆是指对象的保留集中所有的对象的浅堆大小之和。
举例:对象 A 引用了 C 和 D,对象 B 引用了 E。那么对象 A 的浅堆大小只是 A 本身,而如果 A 被回收,那么 C 和 D都会被回收(可达性分析算法),所以 A的深堆大小为 A+C+D 之和,同时由于对象 E 还可以通过对象 B 访问到,因此不在对象 A 的深堆范围内
incoming 和 outgoing
JDK为我们提供的工具
命令行工具

jps

列出当前机器上正在运行的虚拟机进程,JPS 从操作系统的临时目录上去找(所以有一些信息可能显示不全)。
-q :仅仅显示进程,
-m:输出主函数传入的参数. 下的 hello 就是在执行程序时从命令行输入的参数
-l: 输出应用程序主类完整 package 名称或 jar 完整名称.
-v: 列出 jvm 参数, -Xms20m -Xmx50m 是启动程序指定的 jvm 参数

jstat

是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运行数据,在没有 GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。

假设需要每 250 毫秒查询一次进程 13616 垃圾收集状况,一共查询 10 次,那命令应当是:jstat -gc 13616 250 10
常用参数:
-class (类加载器)
-compiler (JIT)
-gc (GC 堆状态)
-gccapacity (各区大小)
-gccause (最近一次 GC 统计和原因)
-gcnew (新区统计)
-gcnewcapacity (新区大小)
-gcold (老区统计)
-gcoldcapacity (老区大小)
-gcpermcapacity (永久区大小)
-gcutil (GC 统计汇总)
-printcompilation (HotSpot 编译统计)

jinfo

查看和修改虚拟机的参数
jinfo –sysprops 可以查看由 System.getProperties()取得的参数
jinfo –flag 未被显式指定的参数的系统默认值
jinfo –flags(注意 s)显示虚拟机的参数
jinfo –flag +[ 参 数 ] 可 以 增 加 参 数 , 但 是 仅 限 于 由 java -XX:+PrintFlagsFinal –version 查 询 出 来 且
为 manageable 的参数

jinfo –flag -[参数] pid 可以修改参数Thread.getAllStackTraces();
1.程序运行时只打印简单 GC

2.通过 jinfo修改 参数,打印 GC 详情

jmap

用于生成堆转储快照(一般称为 heapdump 或 dump 文件)。jmap 的作用并不仅仅是为了获取 dump 文件,它还可以查询 finalize 执行队列、Java 堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。和 jinfo命令一样,jmap有不少功能在 Windows 平台下都是受限的,除了生成 dump 文件的

-dump选项和用于查看每个类的实例、空间占用统计的-histo选项在所有操作系统都提供之外,其余选项都只能在 Linux/Solaris 下使用。
jmap -dump:live,format=b,file=heap.bin <pid>
Sun JDK 提供 jhat(JVM Heap Analysis Tool)命令与 jmap 搭配使用,来分析 jmap 生成的堆转储快照。

jhat

jhat dump 文件名
后屏幕显示“Server is ready.”的提示后,用户在浏览器中键入 http://localhost:7000/就可以访问详情

使用 jhat 可以在服务器上生成堆转储文件分析(一般不推荐,毕竟占用服务器的资源,比如一个文件就有 1 个 G 的话就需要大约吃一个 1G 的资源)

jstack

(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主
要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。
在代码中可以用 java.lang.Thread 类的 getAllStackTraces()方法用于获取虚拟机中所有线程的 StackTraceElement 对象。使用这个方法可以通过简单的几行代码就完成 jstack的大部分功能,在实际项目中不妨调用这个方法做个管理员页面,可以随时使用浏览器来查看线程堆栈。(并发编程中的线程安全课程中有具体的案例)

可视化工具

JMX(Java Management Extensions,即 Java 管理扩展)是一个为应用程序、设备、系统等植入管理功能的框架。JMX 可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。
管理远程进程需要在远程程序的启动参数中增加:
-Djava.rmi.server.hostname=……
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8888
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Jconsole

visualvm

插件中心地址
但是注意版本问题,不同的 JDK 所带的 visualvm 是不一样的,下载插件时需要下对应的版本。
一般来说,这个工具是本机调试用,一般生产上来说,你一般是用不了的(除非启用远程连接)

GC 的重要参数
生产服务器推荐开启

-XX:-HeapDumpOnOutOfMemoryError 默认关闭,建议开启,在 java.lang.OutOfMemoryError 异常出现时,输出一个 dump.core 文件,记录当时的堆内存快照。

-XX:HeapDumpPath=./java_pid<pid>.hprof 用来设置堆内存快照的存储文件路径,默认是 java进程启动位置,。

调优之前开启、调优之后关闭

-XX:+PrintGC
调试跟踪之 打印简单的 GC 信息参数:
-XX:+PrintGCDetails, +XX:+PrintGCTimeStamps
打印详细的 GC 信息
-Xlogger:logpath
设置 gc的日志路,如:-Xlogger:log/gc.log,将 gc.log 的路径设置到当前目录的 log 目录下.
应用场景:将 gc 的日志独立写入日志文件,将 GC 日志与系统业务日志进行了分离,方便开发人员进行追踪分析。

考虑使用

-XX:+PrintHeapAtGC,打印推信息
参数设置:-XX:+PrintHeapAtGC
应用场景:获取 Heap 在每次垃圾回收前后的使用状况
-XX:+TraceClassLoading
参数方法:-XX:+TraceClassLoading
应用场景:在系统控制台信息中看到 class 加载的过程和具体的 class 信息,可用以分析类的加载顺序以及是否可进行精简操作。
-XX:+DisableExplicitGC 禁止在运行期显式地调用 System.gc()

JVM 第五节:JVM 性能优化(上)相关推荐

  1. JVM(五)JVM调优

    文章目录 一.调优实践 1.1 规划 1.1.1 规划步骤 1.1.2 规划案例 1.2 解决JVM运行过程中出现的问题 1.2.1 用jstack定位锁相关问题 1.2.2 OOM问题的定位方式 1 ...

  2. 《如何搭建小微企业风控模型》第五节 特征工程(上)

    <如何搭建小微企业风控模型>第五节 特征工程(上) 第一章 小微企业数据风控技术的框架 小微企业数据贷发展情况概述 搭建小微企业风控模型所需知识 风控模型概览 第二章 强相关变量:企业经营 ...

  3. 总结:Hive性能优化上的一些总结

    Hive性能优化上的一些总结 注意,本文百分之九十来源于此文:Hive性能优化,很感谢作者的细心整理,其中有些部分我做了补充和追加,要是有什么写的不对的地方,请留言赐教,谢谢 前言 今天电话面试突然被 ...

  4. 火云开发课堂 - 《使用Cocos2d-x 开发3D游戏》系列 第二十五节: 3D项目优化方案

    <使用Cocos2d-x 开发3D游戏>系列在线课程 第二十五节:3D项目优化方案 视频地址:http://edu.csdn.net/course/detail/1330/20825?au ...

  5. Java虚拟机:常见JVM参数配置和GC性能优化

    一.常见的JVM参数配置: 1.垃圾回收统计信息: -XX:+PrintGC     打印GC简要信息 -XX:+PrintGCDetails打印GC的详细信息 -XX:+PrintGCTimeSta ...

  6. 阿里三面 Android 研发岗,竟然挂在了性能优化上……

    作为一个程序员,性能优化是无法避开的事情,并且性能优化也是软件系统中最有挑战的工作之一,更是每个工程师都需要掌握的核心技能. 性能问题和Bug不同,后者的分析和解决思路更清晰,很多时候从应用日志即可直 ...

  7. 阿里三面 Android 研发岗,竟然挂在了性能优化上…

    作者:code小生 作为一个程序员,性能优化是无法避开的事情,并且性能优化也是软件系统中最有挑战的工作之一,更是每个工程师都需要掌握的核心技能. 性能问题和Bug不同,后者的分析和解决思路更清晰,很多 ...

  8. 多层科目任意组合汇总报表的性能优化 (上)

    一 问题背景 我们先来看一张资产负债表: 这是一个典型的中国式复杂报表格式,其复杂并不在于布局,而在于其中"期末余额"的每个单元格都是一个需要独立计算的指标,互相之间几乎没有关系, ...

  9. h5如何上传文件二进制流_Hadoop如何将TB级大文件的上传性能优化上百倍?

    这篇文章,我们来看看,Hadoop的HDFS分布式文件系统的文件上传的性能优化. 首先,我们还是通过一张图来回顾一下文件上传的大概的原理. 由上图所示,文件上传的原理,其实说出来也简单. 比如有个TB ...

  10. 代码覆盖率在性能优化上的一种可行应用

    You can't manage what you can't measure. 一件事如果你无法衡量它,你就无法管理它.--管理大师 彼得·德鲁克 前言 JavaScript 是前端应用主要语言,相 ...

最新文章

  1. 0016-Avro序列化反序列化和Spark读取Avro数据
  2. wordpress中remove_action、add_action、 do_action()的hook钩子都有哪些
  3. Qt之布局管理——堆栈窗体
  4. 关于找工作和选专业的思考
  5. access求斐波拉契数列_打印目录,斐波那契数列的递归与循环,牧场牛数
  6. Tensorflow取消占用全部GPU
  7. 51Nod-2149 字符串出现位置【水题】
  8. 2018.10.29-dtoj-4007-飞天鼠小E
  9. 一台液晶显示器台式计算机总耗电量,一天一台电脑用多少电
  10. 装linux双系统有什么好处,科学网—Windows和Linux双系统安装教程 - 戴劭勍的博文...
  11. 左手内容右手科技,讯飞阅读打造适合年轻人的有声阅读APP
  12. iOS-获取手机健康步数,去除人为添加的数据
  13. 【转】Hibernate中session的clear(),flush(),evict()方法详解
  14. 阿里云ECS CentOS 7 安装图形化桌面
  15. 【工具】git 入门
  16. python判断数字位数_python求数字位数的方法
  17. 量子计算或可解救全球芯片危机
  18. IDEA热部署不生效解决方案
  19. 怎样删除我的电脑里的wps云文档图标
  20. 步步高打火机,哪里不会点哪里

热门文章

  1. android 向上弹出,android 弹出Popupwindow 自适用(Activity或者Dialog)判断向上还向下...
  2. nginx php访问阻塞,php-cgi和php-fpm,Windows环境下解决Nginx+php并发访问阻塞问题。
  3. 算法笔记二分查找问题1
  4. java集合源码分析_java集合源码分析(二):List与AbstractList
  5. k8s/docker 安装yapi和MongoDB
  6. mysql 给已存在的商品数据,根据商品ID增加商品编号
  7. 阶段3 1.Mybatis_11.Mybatis的缓存_5 缓存的概念
  8. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_01 File类_6_File类判断功能的方法...
  9. (十四)Struts2 验证框架
  10. 济南学习 Day 5 T1 晚