Java运行时的数据区包括:(其中前两个是线程共享的)
-
1.方法区(Method Area) 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
-
2.堆(Heap) 存放对象实例,几乎所有对象实例都在这里分配内存
-
3.虚拟机栈(VM Stack) 描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个Stack Frame(方法运行时的基础数据结构)用于存储局部变量表、操作数栈、动态连接、方法出口等信息
-
4.本地方法栈(Native Method Stack) 与虚拟机栈了类似,不过则为虚拟机使用的到的Native方法服务。(有的虚拟机譬如Sun HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一)
-
5.程序计数器(Program Counter Register) 可看作当前线程所执行的字节码的行号的标识器
JVM内存总体一共分为了4个部分:
1、stack segment
2、heap segment
3、code segment
4、data segment)
-
当我们在程序中声明一个局部变量的时候,此变量就存放在了 stack segment(栈)当中;
-
当new 一个对象的时候,此对象放在了heap segment(堆)当中;
-
static 的变量或者字符串常量 则存在在 data segment(数据区)中;
-
类中方法是存在在 code segment(代码区)中。
java虚拟机的内存可以分为三个区域:
-
栈stack
-
- 特点:
-
-
- (1)、栈描述的是方法执行的内存模型,每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法入口等);
-
-
-
- (2)、JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等);
-
-
-
- (3)、栈属于线程私有,不能实现线程间的共享;
-
-
-
- (4)、栈的存储特性是 先进后出,后进先出;
-
-
-
- (5)、栈是由系统自动分配,速度快,栈是一个连续的内存空间。
-
-
堆heap
-
- 特点:
-
-
- (1)、堆用于存储创建好的对象和数组(数组也是对象);
-
-
-
- (2)、JVM只有一个堆,被所有线程共享;
-
-
-
- (3)、堆是一个不连续的内存空间,分配灵活,速度慢。
-
-
方法区method area( 位于堆中)
-
- 特点:
-
-
- (1)、JVM只有一个方法区,被所有线程共享;
-
-
-
- (2)、方法区实际也是堆,只是用于存储类、常量相关的信息;
-
-
-
- (3)、用了存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)
-
java运行时数据区
-
运行时数据区包括:虚拟机栈区,堆区,方法区,本地方法栈,程序计数器
-
-
虚拟机栈区 :也就是我们常说的栈区,线程私有,存放基本类型,对象的引用和 returnAddress ,在编译期间完成分配。
-
-
-
堆区 , JAVA 堆,也称 GC 堆,所有线程共享,存放对象的实例和数组, JAVA 堆是垃圾收集器管理的主要区域。
-
-
-
方法区 :所有线程共享,存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。
-
-
-
程序计数器 :线程私有,每个线程都有自己独立的程序计数器,用来指示下一条指令的地址。
-
java内存模型
-
Java线程之间的通信由Java内存模型(简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。
-
- 从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化
-
- volatile变量的写-读可以实现线程之间的通信。
-
- 从内存语义的角度来说,volatile与监视器锁有相同的效果:volatile写和监视器的释放有相同的内存语义;volatile读与监视器的获取有相同的内存语义。
知识点积累
-
1、String str1 = “abc”,“abc”分配在内存字符常量区;
-
2、程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的;
-
3、虚拟机栈描述的是Java方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的;
-
4、原则上讲,所有的对象都在堆区上分配内存,是线程之间共享的