部标GPS通讯系统在上线之后,经过不断调试,终于稳定运行一段时间,后来又遇到了Java heap space错误异常!日志如下:

说明系统中有未释放的对象。如何找出这些未释放对象以及监控JVM堆内存,优化代码释放内存对象呢?还有JVM的垃圾回收机制是如何运作的呢?

首先在系统启动运行的时候打开记录GC详细信息,运行脚本如下:

看看GC详细日志,当GC到13400多次的时候新生代和老生代的堆内存几乎用满了,频繁触发Full GC (Ergonomics) ,直到没有内存空间给新生对象了。所以JVM抛出了内存溢出错误!进而导致程序崩溃。

首先简单了解下JVM垃圾回收机制:

从上图可以看出 GC 的主要收集区域,包括 PSYoungGen(年轻代)、ParOldGen(老年代)、Metaspace(元数据区)。

新生代:新创建的对象都是用新生代分配内存,Eden空间不足时,触发Minor GC,这时会把存活的对象转移进幸存者Survivor区。

老年代:老年代用于存放经过多次Minor GC之后依然存活的对象。

新生代的GC(Minor GC):新生代通常存活时间较短基于Copying算法进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中,对应于新生代,就是在Eden和FromSpace或ToSpace之间copy。

新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从Eden到Survivor,最后到老年代。

老年代的GC(Major GC/Full GC):老年代与新生代不同,老年代对象存活的时间比较长、比较稳定,因此采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,

回收后对用空出的空间要么进行合并、要么标记出来便于下次进行分配,总之目的就是要减少内存碎片带来的效率损耗。

附上堆结构图:

至此,在已经尝试了将Java虚拟机中Xms(初始堆大小-2G)和Xmx(最大堆大小-4G)参数调大之后也无果,只能从代码入手, 对象一直堆积于老年代未被释放,应该是代码中对象未被释放。

为了找出代码中未被释放的对象,这里运用到了内存监控工具jconsole和内存堆对象统计工具jmap。

jconsole.exe位于bin目录下,用法也挺简单的,用于调优后的监控还不错,这里留个图不做介绍了

这里运用jmap(jdk自带的jvm内存分析的工具),将程序堆对象统计出来的结果如下:

发现到代码问题:应该是解析协议的时候CanDataItem对象不断被new出来,使用完了以后并未被GC回收留在老生代,

找到CanDataItem使用完成的地方做了如下修改:

修改代码再将T808Message等类用完了的地方做了释放,之后终于解决了问题!修改代码以后再次使用jmap统计如下,正常了!

附 - jmap输出中class name非自定义类的说明:

BaseType CharacterTypeInterpretation

B

byte

signed byte

C

char

Unicode character

D

double

double-precision floating-point value

F

float

single-precision floating-point value

I

int

integer

J

long

long integer

L;

reference

an instance of class

S

short

signed short

Z

boolean

true or false

[

reference

one array dimension,[I表示int[]

总结导致java.lang.OutOfMemoryError异常的常见原因有以下几种:

内存中加载的数据量过于庞大,如一次从数据库取出过多数据;

集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;

代码中存在死循环或循环产生过多重复的对象实体-----(本例中);

使用的第三方软件中的BUG;

启动参数内存值设定的过小;

至此问题总算解决了,通常情况下,Java开发人员并不需要去关心JVM是如何运行的。即使不理解JVM的工作原理,也不会给开发人员带来过多困惑。Java程序员更容易忽视基础技术。

“蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇蟮之穴无可寄托者,用心躁也”。对于技术人员来说,如果长期忽略自身技术的根基而去一昧地追求高层框架技术,这无疑是舍本求末的做法。

JVM的出现,为程序员屏蔽了操作系统与硬件的细节,使得程序员从诸如内存管理这样的繁琐任务中解放出来。但这不并等同于允许Java程序员放弃对基础的重视。

事实上,任何平台的程序员都应当了解平台的基本特性、实现机制以及接口,这是提高自身修养的必经之路。对于Java程序员来说,我们还是需要多多了解JVM。

了解JVM的基本实现机制,不仅对于解决实际应用中诸如GC等虚拟机问题时有直接帮助,还有利于我们更好地理解语言本身。

转载请注明出处!谢谢!https://www.cnblogs.com/lys_013/p/9605352.html

was java heap space_实战项目中Java heap space错误的解决相关推荐

  1. 视频教程-大型ERP实战项目教程-Java

    大型ERP实战项目教程 十年项目经验,曾经任职中国移动架构师,丰富的教学经验让无数人获得高薪 任亮 ¥1300.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 APP订 ...

  2. junit5_在Java 8之前的项目中使用JUnit 5

    junit5 这篇文章演示了如何在Java 8之前的项目中使用JUnit 5,并解释了为什么它是一个好主意. JUnit 5至少需要Java 8作为运行时环境,因此您想将整个项目更新为Java8.但是 ...

  3. java手机界面太小_手机端页面在项目中遇到的一些问题及解决办法

    原标题:手机端页面在项目中遇到的一些问题及解决办法 来源:键盘上的眼泪 segmentfault.com/a/1190000015178877 1.解决页面使用overflow: scroll在iOS ...

  4. java 获取sqlsession_获取Java的MyBatis框架项目中的SqlSession的方法

    从XML中构建SqlSessionFactory从XML文件中构建SqlSessionFactory的实例非常简单.这里建议你使用类路径下的资源文件来配置. String resource = &qu ...

  5. java项目使用junit_在Java 8之前的项目中使用JUnit 5

    java项目使用junit 这篇文章演示了如何在Java 8之前的项目中使用JUnit 5,并解释了为什么它是一个好主意. JUnit 5至少需要Java 8作为运行时环境,因此您想将整个项目更新为J ...

  6. 在Java 8之前的项目中使用JUnit 5

    这篇文章演示了如何在Java 8之前的项目中使用JUnit 5,并解释了为什么它是一个好主意. JUnit 5至少需要Java 8作为运行时环境,因此您想将整个项目更新为Java8.但是有时由于某些原 ...

  7. 项目中Java的多线程一般用在哪些场景?

    项目中Java的多线程一般用在哪些场景? 多线程使用的主要目的在于 举个简单的例子 伪代码 多线程的常见应用场景 多线程使用的主要目的在于 1.吞吐量:你做WEB,容器帮你做了多线程,但是他只能帮你做 ...

  8. Eclipse 报 “Exception in thread main java.lang.OutOfMemoryError: Java heap space ”错误的解决办法

    Eclipse 报 "Exception in thread "main" java.lang.OutOfMemoryError: Java heap space &qu ...

  9. Eclipse 报 “Exception in thread main java.lang.OutOfMemoryError: Java heap space ”错误的解决办法...

    Eclipse 报 "Exception in thread "main" java.lang.OutOfMemoryError: Java heap space &qu ...

最新文章

  1. 1、win10下连接本地系统上的Linux操作系统(分别以Nat方式和桥接模式实现)
  2. SAP ABAP SQL的execution plan和cache
  3. 第一篇博客,写在颓废之时
  4. inputstream示例_Java InputStream close()方法与示例
  5. jquery.js把我的时间修改了为什么?_电气老手在PLC程序调试修改时的几个必备小窍门,看你知道几个?...
  6. java设置行显示复选框_java spring cheakbox复选框怎么行或者列删除添加
  7. 深入了解Android蓝牙Bluetooth——《基础篇》
  8. win10下zookeeper的下载以及安装
  9. VC++使用ADO开发ACCESS数据库
  10. 下载网页中内嵌的PDF
  11. 修改Android 模拟器IMEI
  12. 完全体,千字详解:“Java性能调优六大工具”之JConsole工具
  13. Qt交叉编译移植arm开发板
  14. 开源 == 文化:红帽社区开放日图文回顾
  15. 苹果电脑系统更新中断怎么办_苹果发布健身公告中断按需锻炼空间
  16. 自定义ActionBar -- 更换返回键图标
  17. 正则匹配里面的(.*?)
  18. 上课签到 php,福建一高校学生上课需刷脸签到 被赞高大上
  19. 软件测试之linux环境搭建与操作Xshell、Xftp
  20. 三次握手与四次挥手简介

热门文章

  1. 不用比较运算符及循环控制语句,判断int型的a、b两数的大小
  2. OpenGL实现3D魔方游戏源代码
  3. 服务器告警其一:硬盘raid问题
  4. SQL AVG() 函数
  5. 2017帝都租房攻略:昌平通州租金涨幅高达25%
  6. 【bzoj1212】[HNOI2004]L语言 AC自动机
  7. 验证多个Filter过滤一个资源时执行顺序
  8. WEB前端技术趋势图示-JS库
  9. Meterpreter重要命令与使用
  10. [Python图像处理] 十六.图像的灰度非线性变换之对数变换、伽马变换