#1、硬件内存和JAVA内存html
#2、JAVA内存模型 按照官方的说法:Java 虚拟机具备一个堆,堆是运行时数据区域,全部类实例和数组的内存均今后处分配。
JVM主要管理两种类型内存:堆和非堆,堆内存(Heap Memory)是在 Java 虚拟机启动时建立,非堆内存(Non-heap Memory)是在JVM堆以外的内存。 简单来讲,堆是Java代码可及的内存,留给开发人员使用的;非堆是JVM留给本身用的,包含方法区、JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存)、每一个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码。java
JVM 内存包含以下几个部分:数组
堆内存(Heap Memory): 存放Java对象
非堆内存(Non-Heap Memory): 存放类加载信息和其它meta-data
其它(Other): 存放JVM 自身代码等缓存
在JVM启动时,就已经保留了固定的内存空间给Heap内存,这部份内存并不必定都会被JVM使用,可是能够肯定的是这部分保留的内存不会被其余进程使用,这部份内存大小由-Xmx 参数指定。而另外一部份内存在JVM启动时就分配给JVM,做为JVM的初始Heap内存使用,这部份内存是由 -Xms 参数指定。安全
#3、JAVA内存分配 Java的内存管理实际上就是变量和对象的管理,其中包括对象的分配和释放。
多线程
JVM内存申请过程以下:并发
#4、JAVA内存间交互操做 关于主内存与工做内存之间的具体交互协议,即一个变量如何从主内存拷贝到工做内存、如何从工做内存同步到主内存之间的实现细节,Java内存模型定义了如下八种操做来完成:app
若是要把一个变量从主内存中复制到工做内存,就须要按顺寻地执行read和load操做,若是把变量从工做内存中同步回主内存中,就要按顺序地执行store和write操做。Java内存模型只要求上述操做必须按顺序执行,而没有保证必须是连续执行。也就是read和load之间,store和write之间是能够插入其余指令的,如对主内存中的变量a、b进行访问时,可能的顺序是read a,read b,load b, load a。Java内存模型还规定了在执行上述八种基本操做时,必须知足以下规则:优化
#5、原子性、可见性、有序性ui
除了volatile以外,Java还有两个关键字能实现可见性,它们是synchronized。同步块的可见性是由“对一个变量执行unlock操做以前,必须先把此变量同步回主内存中(执行store和write操做)”这条规则得到的,而final关键字的可见性是指:被final修饰的字段是构造器一旦初始化完成,而且构造器没有把“this”引用传递出去,那么在其它线程中就能看见final字段的值。 3. 有序性(Ordering)
Java内存模型中的程序自然有序性能够总结为一句话:若是在本线程内观察,全部操做都是有序的;若是在一个线程中观察另外一个线程,全部操做都是无序的。前半句是指“线程内表现为串行语义”,后半句是指“指令重排序”现象和“工做内存主主内存同步延迟”现象。
Java语言提供了volatile和synchronized两个关键字来保证线程之间操做的有序性,volatile关键字自己就包含了禁止指令重排序的语义,而synchronized则是由“一个变量在同一时刻只容许一条线程对其进行lock操做”这条规则来得到的,这个规则决定了持有同一个锁的两个同步块只能串行地进入。
先行发生原则:
若是Java内存模型中全部的有序性都只靠volatile和synchronized来完成,那么有一些操做将会变得很啰嗦,可是咱们在编写Java并发代码的时候并无感受到这一点,这是由于Java语言中有一个“先行发生”(Happen-Before)的原则。这个原则很是重要,它是判断数据是否存在竞争,线程是否安全的主要依赖。
先行发生原则是指Java内存模型中定义的两项操做之间的依序关系,若是说操做A先行发生于操做B,其实就是说发生操做B以前,操做A产生的影响能被操做B观察到,“影响”包含了修改了内存中共享变量的值、发送了消息、调用了方法等。它意味着什么呢?以下例:
//线程A中执行 i = 1;
//线程B中执行 j = i;
//线程C中执行 i = 2;
假设线程A中的操做”i=1“先行发生于线程B的操做”j=i“,那么咱们就能够肯定在线程B的操做执行后,变量j的值必定是等于1,结出这个结论的依据有两个,一是根据先行发生原则,”i=1“的结果能够被观察到;二是线程C登场以前,线程A操做结束以后没有其它线程会修改变量i的值。如今再来考虑线程C,咱们依然保持线程A和B之间的先行发生关系,而线程C出如今线程A和B操做之间,可是C与B没有先行发生关系,那么j的值多是1,也多是2,由于线程C对应变量i的影响可能会被线程B观察到,也可能观察不到,这时线程B就存在读取到过时数据的风险,不具有多线程的安全性。
下面是Java内存模型下一些”自然的“先行发生关系,这些先行发生关系无须任何同步器协助就已经存在,能够在编码中直接使用。若是两个操做之间的关系不在此列,而且没法从下列规则推导出来的话,它们就没有顺序性保障,虚拟机能够对它们进行随意地重排序。
a.程序次序规则(Pragram Order Rule):在一个线程内,按照程序代码顺序,书写在前面的操做先行发生于书写在后面的操做。准确地说应该是控制流顺序而不是程序代码顺序,由于要考虑分支、循环结构。
b.管程锁定规则(Monitor Lock Rule):一个unlock操做先行发生于后面对同一个锁的lock操做。这里必须强调的是同一个锁,而”后面“是指时间上的前后顺序。
c.volatile变量规则(Volatile Variable Rule):对一个volatile变量的写操做先行发生于后面对这个变量的读取操做,这里的”后面“一样指时间上的前后顺序。
d.线程启动规则(Thread Start Rule):Thread对象的start()方法先行发生于此线程的每个动做。
e.线程终于规则(Thread Termination Rule):线程中的全部操做都先行发生于对此线程的终止检测,咱们能够经过Thread.join()方法结束,Thread.isAlive()的返回值等做段检测到线程已经终止执行。
f.线程中断规则(Thread Interruption Rule):对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,能够经过Thread.interrupted()方法检测是否有中断发生。
g.对象终结规则(Finalizer Rule):一个对象初始化完成(构造方法执行完成)先行发生于它的finalize()方法的开始。
h.传递性(Transitivity):若是操做A先行发生于操做B,操做B先行发生于操做C,那就能够得出操做A先行发生于操做C的结论。
一个操做”时间上的先发生“不表明这个操做会是”先行发生“,那若是一个操做”先行发生“是否就能推导出这个操做一定是”时间上的先发生“呢?也是不成立的,一个典型的例子就是指令重排序。因此时间上的前后顺序与先生发生原则之间基本没有什么关系,因此衡量并发安全问题一切必须以先行发生原则为准。
#6、JAVA内存管理 参考文献:http://www.blogjava.net/chhbjh/archive/2012/01/28/368936.html
#7、JAVA安全沙箱 参考文献:https://my.oschina.net/xionghui/blog/499725