如何解决OutOfMemoryError
如果没遇到过OME错误,都不好意思说自己是做Java开发的。
最近更新文章的速度很慢,懒,另外我对时间的分配不太擅长,事情一旦多起来,就很容易焦头烂额,效率也变低,看起来一天忙忙碌碌,最后发现处理的事情并不多。但是在不多的事情中,每天其实在程序开发上都会遇到一些值得分享的事情,如果一直没有动笔记录,很多事情都慢慢的忘记了。所以不管怎么忙,我想还是把工作中遇到技术上的问题,拿出来分享给大家,帮大家少踩坑。也是自己工作的一次记录。
OME的发生
OutOfMemoryError异常可以说是一个比较棘手的问题,Java中所有的对象都存储在堆中,通常如果JVM无法再分配新的内存,内存耗尽,垃圾回收无法及时回收内存,就会抛出OutOfMemoryError。
我这次遇到的OME错误如图:
报错误的原因是因为: 执行垃圾收集的时间比例太大, 有效的运算量太小. 默认情况下, 如果GC花费的时间超过 98%, 并且GC回收的内存少于 2%, JVM就会抛出这个错误。
解决方案
都是自己写的程序,报这个错误,自己心里能没有点数吗,我里面写了一个大对象,实例化之后会不断的加载网络数据到内存中,并且我没有销毁这个对象,继续使用这个对象,同时设置了线程一直让此对象进行等待。
然后我修改大对象在使用之后指向null。压力就没这么大了。
JVM内存区域
可能对JVM了解的不够清晰,下面再整理下JVM的一些常用知识点。
JVM的自动内存管理可以归结为两个问题:
- 给对象分配内存
- 回收分配的内存
经常变动堆内存区域为:新生代(Eden),存活区(Survivor),老年代(Old)
Perm Gen:为持久带,主要存放Java类的类信息,与垃圾收集要收集的Java对象关系
不大。
Code Cache:主要存放代码缓存,它主要用于存放JIT所编译的代码,JIT编译器是在程序运行期间,将Java字节码编译成平台相关的二进制代码。正因为此编译行为发生在程序运行期间,所以该编译器被称为Just-In-Time编译器。JIT主要编译的是热点代码。
关键点:
- 大多数情况下,对象在新生代Eden区中分配,Eden区域不够的时候,虚拟机发动一次Minor GC,对象在发生Minor GC后仍能存活,那么对象将被移动到Suvivor空间中,每经过一次Minor GC,对象的年龄增加1岁,增加到一定的年龄(默认15岁),就会晋升到老年代Old Gen。
- 大对象是指需要连续内存空间的Java对象,典型的大对象是那种很长的字符串及数组。大对象对内存分配来说就是一个坏消息。 像爬虫爬取的整个页面,分配成字符串就是占用内存很多的字符串。
- 在发生MinorGC之前,虚拟机会先检查老年代的最大可用连续空间十分大于新生代的所有对象空间,如果成了,那么Minor GC就是安全的。如果不是,那么检查HandlePromotionFailure是否允许担保失败,如果允许,那么检查老年代的最大可用空间是否大于之前晋升到老年代对象的平均大小,如果大于那么也尝试进行一次Minor GC。 如果小于,或者HandlePromotionFailure设置为不允许冒险,那么改成进行一次Minor GC。
两张Jconsole的JVM图:
常见的JVM设置参数
可以在命令行直接查看可以设置的参数:
-XX:NewRatio:年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)
-XX:SurvivorRatio:Eden区与Survivor区的大小比值
-XX:+DisableExplicitGC 关闭System.gc()
-XX:MaxTenuringThread 对象在Suvivor区域中的年龄到达多少进入Old Gen
-XX:PretenureSizeThreshold 另大于这个设置值的对象直接在老年代分配,避免Eden区和Suvivor区域之间大量的内存分配
这篇文章里面也列举了不少参数:
https://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html
最后
不断的进步。希望能帮助到大家。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
Java 原生网络编程.
一、概念 Java 语言从其诞生开始,就和网络紧密联系在一起。在 1995 年的 Sun World 大会上,当时占浏览器市场份额绝对领先的网景公司宣布在浏览器中支持Java,从而引起一系列的公司产品对Java的支持,使得Java很快成为一种流行的语言。 Java 提供的网络功能的相关类主要有三个,它们分别是URL、Socket、Daragram。 二、URL 和URLConnection URL类代表一个统一资源定位符号,它是指向互联网资源的指针。是这三个类中层次级别最高或者说封装最多的类,通过URL可以直接发送或者读取网络上的数据。 public static void uRLTest(){ try { //URL:统一资源定位符(网址) URL url = new URL("http://www.baidu.com"); InputStream inputStream = url.openStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");...
-
下一篇
新增16条设计规约!阿里巴巴Java开发手册(详尽版)开放下载!
《阿里巴巴Java开发手册》是阿里内部Java工程师所遵循的开发规范,涵盖编程规约、单元测试规约、异常日志规约、MySQL规约、工程规约、安全规约等,这是近万名阿里Java技术精英的经验总结,并经历了多次大规模一线实战检验及完善。这是阿里回馈给Java社区的一份礼物,希望能够帮助企业开发团队在Java开发上更高效、容错、有协作性,提高代码质量,降低项目维护成本。 2018年6月5日,《阿里巴巴Java开发手册》再次刷新代码规范认知,我们新增了16条设计规约! 点此免费下载《阿里巴巴Java开发手册》(详尽版)! 为何要新增设计规约? 脍炙人口的唐诗“两个黄鹂鸣翠柳,一行白鹭上青天”,清爽直接,简明易懂。可读性好的代码也是让人陶醉的,那么如何写出可读性的代码? 代码的可读性是指代码让人容易阅读、理解、调试、可预料的程度。提高代码的可读性可以为
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- MySQL8.0.19开启GTID主从同步CentOS8
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装