Java内存总结

原创 2016年08月29日 15:06:59

一、java内存模型
1.内存模型图形

2.重排序
① 源代码
② 编译器重排序
③ 指令级重排序
④ 内存系统重排序
⑤ 最终执行指令序列
指令级重排序和内存系统重排序,属于处理级重排序。
可能会导致多线程出现内存可见性问题,编译器生成指令,会插入特定类型的内存屏障。
2、volatile内存语义的实现

是否能重排 第二个操作
第一个操作 普通读、写 volatile读 volatile写
普通读、写 YES YES NO
volatile读 NO NO NO
volatile写 YES NO NO
1、当第二个操作是volatile写时,不管第一个操作是什么,都不能重排序。这个规则确 保volatile写之前的操作不会被编译器重排序到volatile写之后。
2、当第一个操作是volatile读时,不管第二个操作是什么,都不能重排序。这个规则确 保volatile读之后的操作不会被编译器重排序到volatile读之前。
3、当第一个操作是volatile写,第二个操作是volatile读时,不能重排序。

1、volatile写之前插入StoreStore屏障;
2、volatile写之后插入StoreLoad屏障;
3、volatile读之后插入LoadLoad屏障;
4、volatile读之后插入LoadStore屏障;
3、锁

在ReentrantLock中,调用lock()方法获取锁;调用unlock()方法释放锁。
ReentrantLock的实现依赖于java同步器框架AbstractQueuedSynchronizer(本文简称之 为AQS)。AQS使用一个整型的volatile变量(命名为state)来维护同步状态,马上我 们会看到,这个volatile变量是ReentrantLock内存语义实现的关键。
4、Final
写final域的重排序规则
禁止把final域的写重排序到构造函数之外。这个规则的实现包含下面2个方面:
1、JMM禁止编译器把final域的写重排序到构造函数之外。
2、编译器会在final域的写之后,构造函数return之前,插入一个StoreStore屏障。这 个屏障禁止处理器把final域的写重排序到构造函数之外。

读final域的重排序规则如下:
1、在一个线程中,初次读对象引用与初次读该对象包含的final域,JMM禁止处理器重排序2、这两个操作(注意,这个规则仅仅针对处理器)。编译器会在读final域操作的前面插入一个LoadLoad屏障。
5、总结
1.jmm内存基本模型

2.Jmm重排序
三个Happen-before:程序顺序性规则、监视器锁规则、volatile规则、传递性。
重排序:编译器重排序、指令级重排序、内存系统重排序。
3.volatile
内存屏障:
volatile写前添加StoreStore屏障;
volatile写后添加StoreLoad屏障;
volatile读后添加LoadLoad屏障;
volatile读后添加LoadStore屏障;
4.final
final读前添加LoadLoad屏障;
final写后添加StoreStore屏障。
final字段不能逃逸构造函数,在访问final字段之前,访问对象之前必须应经被初 始化,初始化对象之前,final字段必须已经被赋值。
5.锁(synchronized、ReentrantLock、concurrent)
AQS中维护一个volatile变量,使用CAS操作内存语义。
二、JVM内存结构
包括:
1、java堆
存储对象,线程共享。OOM
Eden
Old
2、非堆(永久代)
本地方法栈
存储本地方法信息。共有区域。SOF
程序计数器
选择下一条需要执行的字节码指令,分支、跳转、循环等基础功能。私有区域。 OOM
方法区
类型信息(字段、方法)、常量池、静态变量、编译后的代码。共有区域。OOM
JVM栈
栈帧(局部变量表、常量引用、方法返回地址、附加信息、栈计数器),每个方法 调用都创建一个栈帧,该区域是私有的。单线程SOF,多线程OOM。

三、JVM垃圾回收机制
1.垃圾回收算法
标记-清除
标记-(清除)-压缩
复制
增量 分开逐个小区域回收
分代 几个区域不同寿命,一代代回收
并发 停顿
并行 多线程
2、垃圾回收器
年轻代:
Serial:(client模式)
新生代使用复制算法,暂停用户线程;
年老代使用标记整理算法,暂停用户线程;
ParNew:(server模式,多线程版本的Serial收集器)
新生代使用复制算法,暂停用户线程;(多线程)
年老代使用标记整理算法,暂停用户线程;
Parallel Scavenge:(吞吐量优先的收集器)

年老代:
CMS:(响应时间优先(最短回收停顿)的回收器)
使用标记-清除算法
四个阶段:
初始标记
并发标记
重复标记
并发清除

由于CMS会产生浮动垃圾,当回收过后,浮动垃圾如果产生过多,同时因为使用标记-清除算法会产生碎片,可能会导致回收过后的连续空间仍然不能容纳新生代移动过来或者新创建的大资源,因此会导致CMS回收失败,进而触发另外一次FULL GC,而这时候则采用SerialOld进行二次回收。
同时CMS因为可能产生浮动垃圾,而CMS在执行回收的同时新生代也有可能在进行回收操作,为了保证旧生代能够存放新生代转移过来的数据,CMS在旧生代内存到达全部容量的68%就触发了CMS的回收!

Serial Old:(Client)。
年老代使用标记整理算法,暂停用户线程;
Parallel Old:(老生代吞吐量优先的一个收集器)
使用标记整理算法

minorGC:担保GC就是担保minorGC能够满足当前的存储空间,而无需触发老生代的回收,由于大部分对象都是朝生夕死的,因此,在实际开发中这种很起效,但是也有可能会发生担保失败的情况,当担保失败的时候会触发FullGC,但是失败毕竟是少数,因此这种一般是很划算的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

java内存管理总结

  • 2012-04-12 10:03
  • 60KB
  • 下载

java 内存管理总结

  • 2011-05-12 18:03
  • 64KB
  • 下载

关于好的java内存泄漏的文章总结

内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收...

Java内存模型精辟总结

  • 2012-04-17 23:15
  • 578KB
  • 下载

总结:对Java内存模型JMM的理解

JMM规定了线程的工作内存和主内存的交互关系,以及线程之间的可见性和程序的执行顺序。一方面,要为程序员提供足够强的内存可见性保证;另一方面,对编译器和处理器的限制要尽可能地放松。JMM对程序员屏蔽了C...

Java总结——对象内存图解

class Car{ //类的真正意义就是在描述事物。属性和行为统称为事物中的成员。 //成员分两种:成员属性(在代码中的体现:成员变量)和成员行为(代码体现:就是方法。) S...

Java中的内存处理机制和final、static、final static总结

Java程序运行在JVM上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性。所以在学习Java内存分配原理的时候一定要牢记这一切都是在JV...

Tomcat运行Java Web内存溢出总结

如果JVM里运行的程序, 它的内存堆和持久存储区域的都满了,这个时候程序还想创建对象实例的话,垃圾收集器就会启动,试图释放足够的内存来创建这个对象。这个时候如果垃圾收集器 没有能力释放出足够的内存,它...

java虚拟机使用内存知识总结

此文仅供参考,是本人学习java时的总结,有错误麻烦指出,.请友好交流,谢谢! 1.程序计数器   程序计数器(program Counter Register)  占据较小的内存,存放下一条指...

Java中抛出的内存异常总结

Java中抛出的内存异常总结 根据上述的总结:可以整理出来,JVM在运行的时候大致会分为五个区域。方法区、堆区、本地方法栈、虚拟机栈、程序计数器。 其中程序计数器不会报出OutOfMemoryEr...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)