java OutOfMemorry
首先需要明确OOM并不一定会导致程序挂掉,导致服务不可用的是堆内存被耗尽,从而使得主线程直接退出,或者所有工作线程频繁因为OOM异常终止,java分配数组会直接消耗内存,一个对象引用会占用四个字节。
堆内存和栈内存耗尽都会导致OOM
jvm管理的内存大致包括三种不同类型的内存区域:Permanent Generation space(永久保存区域)、Heap space(堆区域)、Java Stacks(Java栈)。其中永久保存区域主要存放Class(类)和Meta的信息,Class第一次被Load的时候被放入PermGen space区域,Class需要存储的内容主要包括方法和静态属性。堆区域用来存放Class的实例(即对象),对象需要存储的内容主要是非静态属性。每次用new创建一个对象实例后,对象实例存储在堆区域中,这部分空间也被jvm的垃圾回收机制管理。而Java栈跟大多数编程语言包括汇编语言的栈功能相似,主要基本类型变量以及方法的输入输出参数。Java程序的每个线程中都有一个独立的堆栈。容易发生内存溢出问题的内存空间包括:Permanent Generation space和Heap space。
第一种OutOfMemoryError: PermGen space
发生这种问题的原意是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够,与Permanent Generation space有关。解决这类问题有以下两种办法:
1. 增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中XX:PermSize是初始永久保存区域大小,XX:MaxPermSize是最大永久保存区域大小。如针对tomcat6.0,在catalina.sh 或catalina.bat文件中一系列环境变量名说明结束处(大约在70行左右) 增加一行:
JAVA_OPTS=" -XX:PermSize=64M -XX:MaxPermSize=128m"
如果是windows服务器还可以在系统环境变量中设置。感觉用tomcat发布sprint+struts+hibernate架构的程序时很容易发生这种内存溢出错误。使用上述方法,我成功解决了部署ssh项目的tomcat服务器经常宕机的问题。
2. 清理应用程序中web-inf/lib下的jar,如果tomcat部署了多个应用,很多应用都使用了相同的jar,可以将共同的jar移到tomcat共同的lib下,减少类的重复加载。这种方法是网上部分人推荐的,我没试过,但感觉减少不了太大的空间,最靠谱的还是第一种方法。
第二种OutOfMemoryError: Java heap space
发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,与Heap space有关。解决这类问题有两种思路:
1. 检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改程序和算法。
我以前写一个使用K-Means文本聚类算法对几万条文本记录(每条记录的特征向量大约10来个)进行文本聚类时,由于程序细节上有问题,就导致了Java heap space的内存溢出问题,后来通过修改程序得到了解决。
2. 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m
第三种OutOfMemoryError:unable to create new native thread
在java应用中,有时候会出现这样的错误:OutOfMemoryError: unable to create new native thread.这种怪事是因为JVM已经被系统分配了大量的内存(比如1.5G),并且它至少要占用可用内存的一半。有人发现,在线程个数很多的情况下,你分配给JVM的内存越多,那么,上述错误发生的可能性就越大。 那么是什么原因造成这种问题呢? 每一个32位的进程最多可以使用2G的可用内存,因为另外2G被操作系统保留。这里假设使用1.5G给JVM,那么还余下500M可用内存。这500M内存中的一部分必须用于系统dll的加载,那么真正剩下的也许只有400M,现在关键的地方出现了:当你使用Java创建一个线程,在JVM的内存里也会创建一个Thread对象,但是同时也会在操作系统里创建一个真正的物理线程(参考JVM规范),操作系统会在余下的400兆内存里创建这个物理线程,而不是在JVM的1500M的内存堆里创建。在jdk1.4里头,默认的栈大小是256KB,但是在jdk1.5里头,默认的栈大小为1M每线程,因此,在余下400M的可用内存里边我们最多也只能创建400个可用线程。 这样结论就出来了,要想创建更多的线程,你必须减少分配给JVM的最大内存。还有一种做法是让JVM宿主在你的JNI代码里边。 给出一个有关能够创建线程的最大个数的估算公式:
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads 对于jdk1.5而言,假设操作系统保留120M内存:
1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB) = ~
380 threads1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads 对于栈大小为256KB的jdk1.4而言, 1.5GB allocated to JVM: ~1520 threads
1.0GB allocated to JVM: ~3520 threads 对于这个异常我们首先需要判断下,发生内存溢出时进程中到底都有什么样的线程,这些线程是否是应该存在的,是否可以通过优化来降低线程数; 另外一方面默认情况下java为每个线程分配的栈内存大小是1M,通常情况下,这1M的栈内存空间是足足够用了,因为在通常在栈上存放的只是基础类型的数据或者对象的引用,这些东西都不会占据太大的内存, 我们可以通过调整jvm参数,降低为每个线程分配的栈内存大小来解决问题,例如在jvm参数中添加-Xss128k将线程栈内存大小设置为128k。
java OutOfMemorry的更多相关文章
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- 异常小结:上一张图搞清楚Java的异常机制
下面是Java异常类的组织结构,红色区域的异常类表示是程序需要显示捕捉或者抛出的. Throwable Throwable是Java异常的顶级类,所有的异常都继承于这个类. Error,Excepti ...
- 一张图搞清楚Java异常机制
下面是Java异常类的组织结构,红色区域的异常类表示是程序需要显示捕捉或者抛出的. Throwable Throwable是Java异常的顶级类,所有的异常都继承于这个类. Error,Excepti ...
- java下载网络大文件之内存不够的解决办法(包含分片上传分片下载)
一.背景 2020年11月份的时候,我做过一个项目,涉及到网络文件,比如第三方接口提供一个文件的下载地址,使用java去下载,当时我全部加在到JVM内存里面,话说,单单是80M的下载单线程没问题,但是 ...
- 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题
背景起因: 记起以前的另一次也是关于内存的调优分享下 有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...
- Elasticsearch之java的基本操作一
摘要 接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...
- 论:开发者信仰之“天下IT是一家“(Java .NET篇)
比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...
- 故障重现, JAVA进程内存不够时突然挂掉模拟
背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...
- 死磕内存篇 --- JAVA进程和linux内存间的大小关系
运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...
随机推荐
- Window权限维持(七):安全支持提供者
安全支持提供程序(SSP)是Windows API,用于扩展Windows身份验证机制.LSASS进程正在Windows启动期间加载安全支持提供程序DLL.这种行为使红队的攻击者可以删除一个任意的SS ...
- Swagger实例分享(VS+WebApi+Swashbuckle)
Swagger实例分享(VS+WebApi+Swashbuckle) Swagger可以很方便的为发布的WebApi自动生成优雅的文档,不需额外自己编写,只需为项目配置好,是一个很好用的工具,做一个简 ...
- Win10 手动安装 WSL 并修改默认登录用户为 root
首先要在"程序和功能"里面开启这个服务 然后重启系统使其生效. 然后打开 PowerShell,输入: Invoke-WebRequest -Uri https://aka.ms/ ...
- [Tomcat源码分析] Eclipse中搭建Apache Tomcat源码调试环境
网上很多文章都推荐使用Ant下载编译,但本地实践中屡屡失败,无法下载. 后来参考 https://blog.csdn.net/xiongyouqiang/article/details/7894107 ...
- java中设置session过期时间
Web容器 apache-tomcat-8.0.26\conf\web.xml中设置 <session-config> <!-- 时间单位为分钟 --> <session ...
- CSS box-sizing属性的正确用法
CSS自定义属性(变量) CSS box-sizing属性允许我们在元素的总宽度和高度中包含填充和边框. 没有CSS box-sizing属性 默认情况下,元素的宽度和高度计算如下: width + ...
- Git 分支代码管理日记备注
1〉 Bithucket 创建代码库 2〉 下载克隆代码 Git clone 代码链接 3〉 代码初始化完成之后,切换到代码文件夹 cd 文件夹名 4〉 查看分支情况 Git brach 5〉 ...
- 【学习笔记】兄弟连LINUX视屏教程(沈超 李明)
发现自己的linux水平楞个瓜皮,找个视屏教程学习一哈 1 linux系统简介 1.1 UNIX和Linux发展史 unix发展历史:1969年,美国贝尔实验室的肯.汤普森开发出unix系统,1971 ...
- 3.dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?
作者:中华石杉 面试题 dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢? 面试官心理分析 继续深问吧,这些都是用 dubbo 必须知道的一些东西,你得知道基本原理,知道序列化是什么协议 ...
- JMETER 审批任务实战
业务场景 我们需要对流程任务进行审批,这个和流程发起是不一样的,因为在流程发起时,只需要用户登录后,指定固定的流程方案和数据就可以发起流程了. 流程任务是需要获取任务ID再做任务审批的. 实现思路 1 ...