1. JAVA内存区域与内存管理
JVM 内存分哪几个区,每个区的作用是什么?
运行时数据区:
-
程序计数器
- 当前线程所执行字节码的行号指示器;
- 空间线程私有,各线程有自己独立的程序计数器,互不干扰;
- 执行Java方法时,计数器记录正在执行的字节码地址,执行本地方法时,计数器值为空(Undefined),该区域不存在OOM。
-
Java虚拟机栈
-
栈帧存储局部变量(基本数据类型、引用类型和returnAdderss类型【指向一条字节码指令的地址】)、操作数栈、动态链接、方法出口信息;
-
空间线程私有,各线程有自己独立的栈帧,每个线程栈的大小 -Xss 设置;
-
线程请求的栈深度大于虚拟机所允许的深度:SOE(StackOverFlow Exception);
虚拟机栈动态扩展时无法申请到足够的内存:OOM(OutOfMemoryError)。
-
-
本地方法栈
- 为虚拟机存储的Native方法服务。线程私有,(OOM,SOE也都存在)。
-
Java堆
- 存放对象实例,大小(-Xms,-Xmx)设置,OOM,线程共享
-
方法区
-
已被虚拟机加载的类信息、常量、静态变量
-
运行时常量池:(方法区的一部分)
-
Byte,Short,Integer,Long,Character,Boolean种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。
-
String类型通过new创建会分配在堆中,通过“ ”创建分配在常量池中;
由只包含“ ”创建的String和+组成的String会被存放在常量池中;
String的intern()方法会查找常量池中是否存在一份equal相等的字符串,如果有则返回引用,如果没有则将自己添加如常量池
String s1 = new String("xyz"); //创建了几个对象?
"xyz"在类加载时已经创建于常量池,运行时将常量池的对象复制一份到堆中,引用交给s1持有。
-
-
-
直接内存(堆外内存)
- 使用Native函数库直接使用本机内存,不受JVM限制,但也会存在OOM