java内存分配
java程序是在jvm上运行的,所以java程序的内存分配是由jvm进行分配管理的
java程序在运行时会分配以下几个区域:
- 程序计数器:又叫寄存器
- 栈:保存局部变量
- 堆:存放动态产生的数据,如new出来的对象
- 方法区:存储被jvm加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
- 常量池:存放常量;存在于方法区(在堆中)
- 代码段:存放源程序代码
- 数据段:存放static修饰的静态成员
程序计数器
JVM支持多个线程同时运行,当每一个新线程被创建时,它都将得到它自己的PC寄存器(程序计数器)。 计数器是每个线程独有的一个内存区域
线程执行java方法,PC寄存器的值将总是指向下一条将被执行的指令,如果方法是 native 的,程序计数器寄存器的值为空
栈(stack)
栈的基本知识
方法被执行时,会创建一个栈帧。
- 存放内容:局部变量-基本类型的变量(byte、short、int、long、float、double)、对象的引用;操作数栈;帧数据区
- 特点:存取速度快;数据的生命周期是方法的运行期间
- 在执行方法时,方法所需的局部变量空间已经建立,方法中定义一个变量,java为变量分配内存空间;当变量的作用域消失,java自动释放掉为该变量分配的内存空间
栈的原理
栈是以帧为单位保存线程的状态
运行一个java程序,jvm创建一个线程,并且为这个线程分配一个栈,java程序的执行是对栈进行操作,程序中的方法在执行时会创建一个栈帧,每个方法的运行就是对栈进行入栈到出栈的操作;
java程序运行,此程序线程激活程序中的方法,jvm就会创建一个栈帧压入此线程的栈中,这个栈帧会存放当前激活方法的参数、方法局部变量等等
栈的异常
创建栈帧时没有内存空间,JVM就会抛出StackOverflowError异常
如果栈扩展时无法申请到足够的内存,将抛出OutOfMemoryError异常
堆(Heap)
栈的基本知识
堆内存:
jvm启动后便会创建一个堆;
- 存放内容:java程序运行时创建的类实例和数组等对象实例
- 特点:可以在运行时动态的分配内存大小;存取速度慢
- 堆内存中出现不再指向的对象,java的垃圾回收器便会定时清理
- 堆内存因为空间满了而无法再进行扩展分配内存时,会抛出java.lang.OutOfMemoryError:Java heap space异常
堆原理
堆是jvm管理所有内存中最重要的一块,所有线程共享的一块区域,在虚拟机jvm启动时创建
堆中存放所有的对象实例,但是对象的引用存在在栈中;
堆空间的释放
jvm对栈中存放的变量,当程序方法运行结束,jvm会自动释放这些变量的内存空间;而对于堆中创建的对象内存空间,在对象不再被使用时,jvm不会自动释放,而是由垃圾收集器进行回收
java垃圾回收器:垃圾收集器基本上都是采用分代收集算法,所以java堆分为新生代和老生代
堆是垃圾收集器主要管理的一部分区域,又称为GC堆
方法区
方法区是被java所有线程共享的内存区域,用于存储已被jvm加载的类信息、常量、静态变量、即时编译器编译后的.class文件中的数据。
方法区无法申请到内存时,将抛出OutOfMemoryError异常
常量池
常量池是方法区的一部分
jvm会为每一个编译后的类创建一个常量池;类编译class文件时,还会生成各种直接常量(基本类型变量、string)和其他类型、方法等符号引用,这部分数据会被存放在常量池中
常量池具有动态性,编译时产生常量池,将.class文件的数据存放进去,在运行期间也可以将新常量放入,如string类的intern()方法可以做到;所以常量池又称为运行时常量池
对象内存分析
1 | class Phone{ |
以下是内存分析图