A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 我爱睡觉 中级黑马   /  2016-1-22 14:59  /  475 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

堆简史
Java的堆存储是由操作系统分配给JVM的。所有的Java对象都通过堆存储JVM位置/标识来引用。你在堆存储上运行一个对象必定会引用两个堆区域其中之一。这些区域更确切来说为一代。明确来分为:(1)年轻代 (由EDEN和两个SURVIVOR子空间组成) 和 (2) 年老代。 (注:Oracle日前宣布,持久代在JDK7中开始逐步淘汰,而在JDK8将会完全被淘汰)。所有的代都遭受了可怕的“全部停止(Stop-the-World)”完全垃圾回收事件,除非你使用“少量暂停”回收机制例如Azul的Zing.
在垃圾回收的世界里,操作是由“回收机制”执行的,这些回收器的操作对象是堆的“代”(以及子空间)的目标。回收器在堆栈/空间目标中进行操作。完整的垃圾回收是如何工作的内部细节是它自己本身一个(非常大的)主题,有专门的文章会提到。



现在知道一点:如果任何回收器(任何类型的)操作任何一代的堆空间都会造成“停止一切(Stop The World)”的事件——这是一个非常严重的问题。
这是一个问题必须得有个解决方案。
这是一个问题只有非堆存储JEP可以解决。
让我们仔细看看。
Java堆布局: 查看它的历代
垃圾回收使得编程变得更加容易,但是在SLA目标的世界里,无论是书面的还是暗示的(我的Java Applet暂停30秒不是一种选择),停止一切(Stop-The-World)时间暂停对于许多Java开发人员来说是一个很头疼的问题,摆在他们面前的只有性能问题。顺便提一下,还有许多其他性能问题需要处理,只有在STW不再是问题的时候。


使用off-heap存储的好处,就是中等寿命对象的数量可以大幅度下降。它甚至也可以降低短寿命对象的数量。对于高频交易系统,它一天可以创建的垃圾比你的Eden空间大小还要小,这意味着你可以运行一整天而不需要一个简单的回收。一旦你有非常低的内存压力,以及部分对象已经到达年老代(tenured)空间,调整你的GC就会变得很琐碎。通常你甚至不需要设置GC的参数(除非希望增加eden区的大小)。
通过移动对象到非堆存储,Java应用程序往往能够收回监管控制自己的命运,满足SLA性能的期望和义务。



等一下,刚刚最后一句说啥来着?
注意:所有乘客,请收起你的托盘并坐直来。OpenJDK非堆存储JEP的中央租户是一个非常值得重复的事情。
移动回收(如HashMap)到非堆存储,Java应用程序经常能够请求他们的回收(不再依赖于STW的GC机制中的“紧急暂停”事件)去控制他们自身的命运,满足SLA性能的期望和义务。
这是一个很实用的选择,在Java的高频率交易系统中已经在使用。
这个选择也彻底需要Java保持着对高性能计算越来越多的吸引力。
堆存储的优势
  • 常见的,写普通的Java代码。所有有经验的Java开发人员都可以做到。
  • 访问内存的安全性问题。
  • 自动的GC服务——无需自身管理的malloc()/free()操作。
  • 完整的 Java Lock API和JMM相结合。
  • 添加无序列化/复制数据到一个结构中去。

非堆存储的优势
  • 控制"停止一切(Stop the World)"的GC事件到你比较满意的层次。
  • 可以超越在规模上的堆存储结构(当使用堆存储的时候会变得很高)
  • 可以作为一个本地的IPC传输(无需java.net.Socket的IP回送)
  • 分配器的注意事项:


    • NIO DirectByteBuffer到/dev/shm (tmpfs)的map?
    • 或者直接sun.misc.Unsafe.malloc()?




0 个回复

您需要登录后才可以回帖 登录 | 加入黑马