javaSE学习-基础3-java内存分析

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就会创建一个栈帧压入此线程的栈中,这个栈帧会存放当前激活方法的参数、方法局部变量等等

javaSE_基础_内存_栈帧

栈的异常

创建栈帧时没有内存空间,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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Phone{
String brand;
String color;
int price;
Phone(String brand,String color,int price){
this.brand = brand;
this.color = color;
this.price = price;
}
public void call(String name){...}
public void sendMessage(String name){...}
}
class PhoneAct{
public static void main(String[] args){
Phone p = new Phone("三星","银色",3000);
}
p.call("爸爸");
p.sendMessage("妈妈");
Phone p2 = new Phone("苹果","金色",6000);
p.claa(“朋友”);
}

以下是内存分析图

javaSE_基础_内存_对象内存图