推广 热搜: 公司  快速  中国  上海  未来    企业  政策  教师  系统 

java stream 防内存溢出 java poi内存溢出

   日期:2024-11-12     作者:caijiyuan    caijiyuan   评论:0    移动:http://kaire.xrbh.cn/news/10512.html
核心提示:1、idea报java.lang.OutOfMemoryError: Java heap space怎么解决?2、java.lang.OutOfMemoryError: GC overhead limit exceeded

1、idea报java.lang.OutOfMemoryError: Java heap space怎么解决?

java stream 防内存溢出 java poi内存溢出

2、java.lang.OutOfMemoryError: GC overhead limit exceeded怎么解决?

3、xssfworkbook导出Excel内存溢出?

4、如何查看jvm内存使用情况?

应用配置:idea+tomcat7+informix+jdk7+poi3.9

本地机器的物理内存为8G,没有对JVM进行配置。

场景:从数据库查询大批量数据(其实就2万条数据),List存放2万条数据,利用poi,通过自己写的Excle数据导出工具,对数据进行处理,并以Excel文件的形式进行导出(会创建1个或多个sheet页)。创建Excle调用的方法如下(Utils中有Excle上传及导出工具,此处不再粘贴代码):

在导出Excle文件时,出现下述异常:

当未对JVM进行配置时,出现异常一,原因如下:Excle工具采取poi框架对Excle进行导出导致的JVM内存溢出。原因是所创建的book sheet row cell 等,此时是存在内存的,并没有 持久化,那么随着数据量增大内存的需求量也就增大,那么很大可能就是要 OOM了。而我本地并未对JVM进行配置,均采用的默认配置。当导出2万条数据时,就导致了内存溢出。(测试了下,在准备金系统的开发环境也有该问题,测试环境与生产环境还未出现OOM问题(内存足够))。

然后我对JVM进行了配置(JVM模块会对JVM调优进行详细说明):

在进行导出时,出现了下述异常:

我进行了下述配置(下面会对如何对服务进行JVM配置进行详细说明):

虽然偶尔可以导出成功,但确实,大多数情况下报异常一。这也证实了上述所述的原因。

我通过java自带的jconcole工具查看了当进行导出时,JVM占用内存的变化情况,如下图:15:00之前是当数据量在1万条左右时,多次导出,堆内存使用量在1G浮动,但仍可以正常进行导出。15:00以后是当导出的数据条数达到2万后,当第一次启动服务,并导出时,可能会导出成功一次,往后均OOM。15:30是一段时间没进行导出操作后,对内存使用量才降下来的。(下面会详细说明怎么查看JVM的内存使用量)

 

java stream 防内存溢出 java poi内存溢出_堆内存

通过上述分析,可以得出结论,导致内存溢出的原因,就是poi的Excel导出工具占用的内存太大。

上述通过对异常的分析,我们找到了异常出现的原因,是poi在进行Excel导出时,占用了大量的内存空间。解决方案如下,两种方案:

第一种:当数据量并不是特别大的时候,可以通过设置JVM的内存,导出大批量的数据。但是当数据量达到百万后,只有通过方案二来解决。

第二种:通过SXSSFWorkbook来导出。

下面我们详细的分析两种解决方案。

上面已经有了,不再赘述,对参数进行简单说明:

堆(Heap)和非堆(Non-heap)内存

按照官方的说法:“Java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在Java虚拟机启动时创建的。”“在JVM中堆之

外的内存称为非堆内存(Non-heapmemory)”。可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用

的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。

堆内存分配

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增

大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC后调整堆的大小。

非堆内存分配

JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

JVM内存限制(最大值)

首先JVM内存限制于实际的最大物理内存(废话!呵呵),假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可

控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。

主要通过以下的几个jvm参数来设置堆内存的:

-Xmx512m 最大总堆内存,一般设置为物理内存的1/4

-Xms512m 初始总堆内存,一般将它设置的和最大堆内存一样大,这样就不需要根据当前堆使用情况而调整堆的大小了

-Xmn192m 年轻带堆内存,sun官方推荐为整个堆的3/8

-Xss 为jvm启动的每个线程分配的内存大小,默认JDK1.4中是256K,JDK1.5+中是1M

堆内存的组成 总堆内存 = 年轻带堆内存 + 年老带堆内存 + 持久带堆内存

年轻带堆内存 对象刚创建出来时放在这里

年老带堆内存 对象在被真正会回收之前会先放在这里

持久带堆内存 class文件,元数据等放在这里

-XX:PermSize=128m 持久带堆的初始大小

-XX:MaxPermSize=128m 持久带堆的最大大小,eclipse默认为256m。如果要编译jdk这种,一定要把这个设的很大,因为它的类太多了。

关于JVM的调优及配置说明等等,网上的各种资料、博客繁杂庞多,看的我是头昏眼花,还有一大部分是搬运工,没有自己做过配置,理解。这里不再进行代码搬运。关于JVM的调优应该是一个专门的课题来研究,下面我会自己看资料,写专门的博客。现在只是解决我在项目中遇到的问题,不做深究。

使用SXSSFWorkbook 导出进行数据导出。详见链接:

但是这种方式没有自定义颜色的方式。

自己的Excel文件导出工具,详见链接:

如果错过太阳时你流了泪,那你也要错过群星了。在所有的矛盾中,要优先解决主要矛盾,其他矛盾也就迎刃而解。不要做个笨蛋,为失去的郁郁寡欢,聪明的人,已经找到了解决问题的办法,或正在寻找。

本文地址:http://syank.xrbh.cn/news/10512.html    迅博思语资讯 http://syank.xrbh.cn/ , 查看更多
 
标签: 溢出 内存
 
更多>同类资讯
0相关评论

新闻列表
企业新闻
推荐企业新闻
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  粤ICP备2023022329号