内存管理
- Java栈区(内存管理中最重要的模块)
作用: 它存放的是Java方法执行时的所有的数据
栈区由栈帧组成,一个栈帧代表一个方法的执行
这就解释了为什么栈可以完整的描述java中的方法嵌套调用
-
Java栈帧
作用:每个方法从调用到执行完成就对应一个栈帧在虚拟机栈中入栈到出栈的一个过程
举个栗子:
比如A方法运行时要调用B方法,在A方法中执行到调用B的那条语句时,Java虚拟机会创建一个保存B方法的一个栈帧,然后被压入Java栈区中,当B方法执行完之后,栈帧从Java栈区中弹出。栈帧主要包括:
- 局部变量表
- 栈操作数
- 动态链接
- 方法出口
异常 stackoverflow 就是在栈区中出现的,出现的原因:当栈的深度大于JVM所允许的最大深度时
模拟异常,写一个没有退出的递归函数
public class Digui { public static void main(String[] args){ System.out.println("输入一个整数:"); Scanner scan = new Scanner(System.in); int x = scan.nextInt(); judgePrime(x); } static void judgePrime(int n) { judgePrime(n+1); } }
会产生异常
Exception in thread "main" java.lang.StackOverflowError
-
本地方法栈
本地方法栈是专门为native方法服务的
-
方法区
作用:存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后等数据
特点:主要存储编译期所要保存的信息,永远占据内存
-
堆区
作用:所有通过new创建的对象的内存都在堆中分配
特点:是虚拟机中最大的一块内存,是GC要回收的部分
堆区内容分配:
新生代:新建的对象都是用新生代分配内存
旧生代:用于存放新生代中经过多次垃圾回收仍然存活的对象
当Eden空间不足的时候,java虚拟机会通过一系列的算法和规则,会把存活的对象转移到老生代区,当新生代和老生代都没有足够的存储时,这个时候JVM会抛出OOM异常,并且垃圾回收器会重点回收新生代和老生代的内存区域
开发人员可以根据自己项目的需求去动态的调整新生代和老生代的区域大小。
举个栗子
在做即时通信的应用时,因为临时消息会比较多,所以可以将新生代的区域调大,老生代的区域调小,这样便于内存的分配,加快对象的创建。如果开发大型服务类程序时,可以将新生代的区域调小,老生代的区域调大,达到对象常驻内存的效果,增加服务器的稳定性。