码迷,mamicode.com
首页 > 编程语言 > 详细

Java:内存相关认识

时间:2015-06-01 14:49:10      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:java   内存   

JVM管理的内存

  • 程序计数器(PC):每条线程都有独立的PC
  • JVM栈(Java栈):描述的是Java方法执行的内存模型,每个方法被执行的时候会创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息,也是线程私有的。
  • 本地方法栈:与Native方法相关
  • Java堆:线程共享的内存地址空间,用于存放对象实例,也是GC管理的主要区域。
  • 直接内存:与Native堆相关
  • 方法区:存储已被JVM加载的类信息、常量、静态变量等数据,这个区域的内存回收目标主要针对常量池的回收和类的卸载。方法区也是线程共享的内存区域,虽然被描述为堆的一个逻辑部分,但别名为非堆(Non-Heap)。
  • 运行时常量池:方法区的一部分,常量池存放编辑期生成的各种字面量和符号引用,当类加载后则存放到方法区的运行时常量池。

内存分配规则

  • 对象优先在Eden区分配,Minor GC(新生代GC)后对象不足以放进Survivor区则进入老年代。
  • 大对象直接进入老年代
  • 长期存活的对象讲进入老年代:通过年龄计数器来实现。
  • Survivor同龄对象大小之和大于空间一半,大于这个年龄的对象进入老年代。
  • 判断晋升老年代对象是否大于老年代所剩空间,是则进行Full GC(老年代GC)。

GC回收相关

PC、Java栈、本地方法栈随线程和方法的生命周期,因此内存分配与回收具有确定性。
Java堆和方法区只有在运行期间才能知道需要创建哪里对象,这部分内存分配和回收是动态的,GC关注这部分的内存。通过根追溯(Root Tracing)法,即一条引用链来判断对象存活,来确定是否回收对象(引用计数法不能解决对象相互引用等问题)。方法区主要回收废弃常量和无用的类。

垃圾回收算法:

  • 标记清除算法(Mark-Sweep):回收后会造成内存不连续
  • 复制算法(Copying):将内存分为一块较大的Eden空间和两块较小Survivor空间,将Eden和其中一个Survivor存活对象复制到另外一块Survivor空间,最后回收前面那两个空间。当Survivor空间不够时,由老年代空间进行分配担保。新生代对象中大部分都是朝生夕死的,所以常采用这种算法来回收新生代。
  • 标记整理算法(Mark-Compact):将所有存活对象移向一端,直接清理其他端边界以外的对象。
  • 分代收集:根据对象的存活周期将不同的内存划分为几块,一般分为新生代(Young)和老年代(Old),对不同年代采取不同回收算法。例如,对新生代采取复制算法,对老年代采取标记清除或标记整理回收算法。

一个虚拟机可以有多个不同的GC,如HotSpot就有7种作用于不同年代的GC,另外GC关注的线程数目(单线程还是多线程)也可能是不同的。


Java内存模型

JVM试图定义一种内存模型来屏蔽各种硬件和操作系统间内存访问差异,以实现在各个平台都能达到一致的并发效果。

技术分享

内存间的相互操作:

  • lock
  • unlock
  • read
  • load
  • use
  • assign
  • store
  • write

当一个变量被定义为volatile之后具备两种特效:可视性和禁止重排序。可视性的意思可以粗略理解为,虽然进行了原子操作,但是并不保证另外的线程看到的是最新修改后的值,可视性则保证最新值已经刷新到了主内存。重排序的意思是:不能保证变量赋值操作的顺序与代码的执行顺序一致,如果在本线程内观察,所有的操作都是有序的,即线程内有串行的语义;如果在一个线程观察另外一个线程,由于指令重排序,操作可能是无序的。


参考:
《深入理解Java虚拟机》
http://www.th7.cn/Program/java/201409/276272.shtml

Java:内存相关认识

标签:java   内存   

原文地址:http://blog.csdn.net/leelit/article/details/46308951

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!