HOME/Articles/

java内存模型

Article Outline

Java内存模型

其实谈到java内存模型,之前总是觉得这些是需要背的,但是其实仔细想想,还是有规律可循的。

原生类型和对象类型

  • 每个线程都有自己的线程栈,并且只能访问自己的线程栈,每个线程都不能访问其他线程的局部变量(线程隔离)
  • 所有原生类型的局部变量都存储在线程栈中,因此对其他线程都是不可见的状态,线程可以将一个原生变量值的副本传给另一个线程,但是不能共享原生局部线程本身。
  • 堆内存中包含了Java代码中创建的所有对象,不管是哪个线程创建的,其中也包含了包装类型,不管是创建一个对象并将其赋值给局部变量还是赋值给另一个对象的成员变量,创建的对象都会被保在对内存中。
  • 每启动一个线程,jvm就会在栈空间分配对应的线程栈(-Xss1m --每个线程栈使用1M空间)
  • 线程栈也叫做Java方法栈,如果使用JNI方法,则会分配一个单独的本地方法栈
  • 线程执行过程中,一般会有多个方法组成调用栈,如A调用B,每执行到一个方法,就会创建对应的栈帧。
  • 堆是所有线程共用的内存空间,又分为年轻代和老年代。

<!--其实,以上这些特点,可以大致总结一下,java中的变量,有原生类型和对象类型(包括包装类),原生类型是放在Java线程栈中的,即这个变量属于哪个线程,就放在对应的线程栈中;而对象类型和包装类,不管哪个线程的,都是统一放在堆中的。-->

分代问题与内存划分

分代假设

大部分新生的对象,很快就会无用,而长时间存活的对象,可能存活更长时间。基于这个分代假设,堆又被分成几块,老年代,新生代,非堆 。

14923529-c0cbbccaa6858ca1.png

新创建的对象,是放在新生代的Eden的,在eden满了或没有空间分配新的对象(或其他情况)的时候,会触发young gc,而在多次young gc后仍然存活的对象,会转移到old区。

1、引出问题:现在知道了,对象是放在堆的,而各个线程都可以访问堆,那么则产生了线程安全问题,