本地方法栈、java堆、方法区、运行时常量池
本地方法栈
- 简介
⽤于作⽤域本地⽅法执⾏的⼀块Java内存区域
- 本地方法就是native方法
import java.util.concurrent.atomic.AtomicInteger;
public class A {
public native static void c();
public static void a(){
System.out.println("enter method a");
}
public static void b(){
a();
System.out.println("enter method b");
}
public static void main(String[] args) {
b();
System.out.println("enter method main");
AtomicInteger atomicInteger = new AtomicInteger(1);
atomicInteger.compareAndSet(1,2);
}
}
- 作用
与Java虚拟机栈相同,每个⽅法在执⾏的同时都会创建⼀个栈帧(Stack Framel)⽤于存储局部变量表、操作数栈、动态链接、⽅法出⼝等信息。
每⼀个⽅法从调⽤直⾄执⾏完成的过程,就对应着⼀个栈帧在虚拟机栈中⼊栈到出栈的过程
- 特点
Hotshot将Java虚拟机栈和本地⽅法栈合⼆为⼀
Hotshot只是jvm的一种实现
java堆
- 简介
是Java内存区域中⼀块⽤来存放对象实例的区域,【⼏乎所有的对象实例都在这⾥分配内存】
- 作用
此内存区域的唯⼀⽬的就是存放对象实例
Java 堆(Java Heap)是 Java 虚拟机所管理的内存中最⼤的⼀块 Java 堆是被所有线程共享的⼀块内存区域
- 特点
Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”(Garbage)
可配置 -Xmx -Xms
Java堆可以分成新⽣代和⽼年代,新⽣代可分为 To Space、From Space、Eden
- 案例
任意启动1个java项目
cmd中输入 ps -eflgrep java
查看到当前应用的进程pid
sudo jmap -heap pid
查看java堆
方法区
- 简介
是各个线程共享的内存区域,它⽤于存储已被虚拟机加载的类信息、常量、静态变量、即时
编译器编译后的代码等数据
什么是类信息:类版本号、⽅法、接⼝
- 作用
内存中存放类信息、静态变量等数据,属于线程共享的⼀块区域
Hotspot使⽤永久代来实现⽅法区 JRockit、IBM J9VM Java堆⼀样管理这部分内存
- 特点
并⾮数据进⼊了⽅法区就如永久代的名字⼀样“永久”存在了。这区域的内存回收⽬标主要是针对常量池的回收和对类型的卸载
⽅法区也会抛出OutofMemoryError,当它⽆法满⾜内存分配需求时
运行时常量池
- 简介
运⾏时常量池是⽅法区的⼀部分,Class⽂件除了有类的版本、字段、⽅法、接⼝等描述信息外,还有⼀项信息是常量池,⽤于存放编译器⽣成的各种字⾯量和符号引⽤,这部分内容将在类加载后进⼊⽅法区的运⾏时常量池中存放。
- 运⾏时常量池的模拟
public class A {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
System.out.println(a==b);
String c = new String("abc");
System.out.println(a==c);
System.out.println(a==c.intern());
}
}
# 控制台打印结果
true
false
true
-
分析
-
第1个true是因为栈中a和b指向运行时常量池
-
第2个为false,是因为a指向运行时常量池,c指向堆
-
第3个为true,是因为intern方法将c移动到运行时常量池
-
特点
运⾏时常量池是⽅法区的⼀部分,受到⽅法区内存的限制,当常量池再申请到内存时会抛出OutOfMemoryError异常