Java 的内存大小与垃圾回收简述

一些 Java 程序在高负荷时性能会出现显著下降。一个可能的原因是没有设定恰当的内存大小(memory sizing),导致垃圾回收(Garbage collection,下称 GC)频繁执行。即使 CPU 满负荷运作,性能依然较差。

JVM 的内存分 Java 专用区域与 C Heap 两部分,其中前者又分为维护 Java 对象的 Java Heap 区域与维护类信息的 Permanent 区域。一些采用了分代收集机制(Generational Garbage Collection,或称 Generation Scavenging)的 GC 系统还将 Java Heap 进一步细分为 Eden、Survivor 与 Old 区域。Eden 维护生成的对象,GC 时未被回收的对象将被移入 Survivor,长期存在的对象进一步进入 Old 区域。

对于分代收集,GC 可分为 Full GC 与 Copy GC,其中,Copy GC 仅针对 New 区域(Eden+Survivor),Full GC 则针对所有区域。为防止 GC 过于频繁,我们需要设置合适的内存大小。常见的情况有以下这些:

Copy GC

  • Eden 区域空间不足

Full GC

  • Eden 区域空间不足时,Old 区域的可用内存大小不足以容纳 New 区域的已使用内存
  • New 区域与 Old 区域的可用内存空间不足
  • GC 后 Old 区域的剩余空间过低
  • GC 后 Old 区域的空间增加
  • Permanent 区域的可用空间不足

在程序执行过程中,Permanent 区域很少发生变化,因此我们因主要考虑 Full GC 的前两种情况。未避免 Old 区域的空间增加,建议将 Java Heap 的初始值与最大值设为同一值。

通常,Full GC 更为耗时,因此我们应主要考虑减少 Full GC,令 Copy GC 可以解决大部分回收。为此,Old 区域的内存大小是一个关键。

Old 区域的内存大小应与 Java 程序占用内存、Java 服务器占用内存,及 New 区域的内存大小,之和,相当。

举例来说,对于 Web 程序,事务处理占用的内存可以被立即释放,会话占用的内存则需要长期保存。因此后者应归为 Java 程序占用内存。

New 区域的内存大小也需要专门考虑,尤其是 Survivor 区域的大小十分重要。如果 Survivor 区域的内存大小不足,对象就需要被移动至 Old 区域。如果这些对象的生存周期不够长,就会进一步引发 Full GC。增加 Survivor 区域可以缓解该问题。然而,如果 Survivor 区域过大,Copy GC 的处理时间就会增加。因此,应当设置一个阀值,将经历 Copy GC 次数超过该值的对象移植 Old 区域。应尽可能避免 Survivor 区域已满,对象从 Eden 区域直接被移动至 Ole 区域的情况。为此,需要在 Copy GC 发生后检查 Survivor 区域是否被完全占用,以及移动至 Old 区域的对象年龄(生存次数)是否合适。如有可能,应为 Survivor 区域分配较大的内存大小,以适应需求。具体的内存大小估算方式,可以查找其他相关文章。

Eden 区域的内存大小将直接影响 Copy GC 的频率。通常,每发生 10-20 次 Copy GC 后执行一次 Full GC 较为合适。

Documentum 上传大尺寸文件

说明:

Documentum API (DFC) 提供了多种文件上传方法,如果需要上传的文件较大,则需要选择合适的方法。

其中,SetContent()及相关扩展方法需要使用 Byte 数组构造文件内容,因此会消耗较多内存,抛出 java.lang.OutOfMemoryError: Java heap space 异常。可以通过配置 JRE 的 Xms 参数(例:-vmargs -Xmx1024M 表示为 JVM 分配最少1024MB内存)增加内存分配以在一定程度上缓解该问题,但如果系统内存不足,将无法启动程序。

另一方面,SetFile()及相关扩展方法可以接收文件路径,无需将整个文件载入内存,但却需要耗费额外存储空间。应记得在完成处理后删除临时文件。

顺便一提,造成 heap space 不足通常可能有以下原因:线程过多、 java.io.File 类的 deleteOnExit() 方法维护的文件信息过多、大量 I/O 操作、java.util.zip 包的 Deflater 与 Inflater 类的构造函数在 end() 方法被调用前保存了大量信息、java.nio.ByteBuffer 类的 allocateDirect() 或 java.nio.channels.FileChannel类的 map() 方法生成了大量 Buffer 对象实例。

世界最薄最轻量——索尼(Sony)发表平板电脑 Xperia Z4 Tablet

Xperia Z4 Tablet似曾相识的标题。一年之后,索尼又刷新了当时由 Xperia Z2 Tablet 创造的世界最薄最轻量记录(WiFi 版6.4mm、 427g),在推出了仅重389g(WiFi版,LTE 版为393g)、厚6.1mm的 Xperia Z4 Tablet,成为了世界最轻博的10寸级别(10.1寸)平板电脑。

Xperia Z4 Tablet 采用了一块 WQXGA 分辨率(2,560×1,600)的超高清 LTPS 液晶屏、Qualcomm Snapdragon 810 处理器、3GB内存、32GB存储空间、后置810万象素 Exmor RS for Mobile 传感器摄像头、前置25mm广角500万象素摄像头、支持 IEEE 802.11a/b/g/n/ac 与 Bluetooth 4.1。

  •  Z4 Tablet 的 LTPS 屏幕亮度为前代 Z2 Tablet 的140%,在任意角度下明亮清透
  • TRILUMINOS™ display with Live Colour LED 技术实现了130% sRGB 超广色域
  • Cat 6 LTE 通信模块实现了最大300Mbps的网络速率
  • 液晶记忆技术与高性能电池,使得 Z4 Tablet 拥有长达17小时的高清视频播放能力
  • USB 接口防水。耳机插口防水
  • 数字降噪、DSEE HX (Digital Sound Enhancement Engine)
  • PS4 Remote
  • LDAC™ 高解析度蓝牙音乐协议

Z4 Tablet 是十分令人兴奋的产品,决定首发入手。

 

此外索尼还一同公布了中端防水机型 Xperia M4 Aqua。整体设计承袭自 Z3,但硬件规格有所缩减,价格也更加平易近人。

 

本文图像版权属于相关版权所有者