Native、方法区、栈
在java文件中,凡是带了native关键字的,说明java作用范围达不到了,调用底层C语言的库。
方法会进入“本地方法栈”,调用本地方法接口JNI(JNI作用:扩展java的使用,融合不同的编程语言。)
java在内存区域中专门开辟了一块标记区域:Native Method Stack,登记native方法,在最终执行的时候,加载本地方法库中的方法通过JNI
PC寄存器
每一个线程都有一个程序计数器(Program Counter Register),是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向一条指令的地址,也将要执行的指令代码),执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。
方法区
方法区被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义。==》所有定义的方法的信息都保存在该区域(共享)
静态变量、常量、类信息(构造方法,接口定义)、运行时的常量池存在方法区中,实例存在堆内存中
package com.ex;
public class Test {
public static void main(String[] args) {
new Test().test();
}
public void test(){
}
}
栈
先进后出,后进先出。
栈内存,主管程序的运行,生命周期和线程同步。
栈运行原理:栈帧
Hotspot、堆
三种JVM:
Sun
: Java HotSpot™ 64-Bit Server VM (build 25.241-b07, mixed mode)
BEA
:JRockit
IBM
:J9 VM
堆
Heap
-
一个JVM只有一个堆内存
-
堆内存分区:
1. 新生区 Young/New
2. 养老区 old
3. 永久区 Perm用来存放JDK自身携带的Class对象。Interface元数据,存储的是java运行时的一些环境或者类信息,这个区域不存在垃圾回收,关闭JVM即释放。 一个启动类,加载了大量的第三方jar包。Tomcat部署了很多应用,大量动态生成的反射类,不断的被架子啊,直到内存满,出现OOM
- jdk1.6之前:永久代,常量池在方法区
- jdk1.7 : 永久代,退化了,提出了
去永久代
,常量池在堆中 - jdk1.8:无永久代,常量池在元空间
垃圾回收(轻量级(轻GC)、重量级(重GC or Full GC)):主要在伊甸园和养老区进行垃圾回收。
当一个对象经历了15次GC,就进入了老年区
package com.ex;
public class Test {
public static void main(String[] args) {
//虚拟机试图使用的最大内存
long maxMemory = Runtime.getRuntime().maxMemory();
System.out.println("maxMemory = "+(maxMemory/(double)1024/1024)+" byte");
//JVM初始化总内存
long totalMemory = Runtime.getRuntime().totalMemory();
System.out.println("totalMemory = "+(totalMemory/(double)1024/1024)+" MB");
}
}
手动扩大
VM options:
-Xms`数值`m -Xmx`数值`m -XX:+PrintGCDetails
-Xms`数值`m -Xmx`数值`m -XX:+HeapDumpOnOutOfMemoryRrror
//OOM
package com.ex;
import java.util.Random;
public class OOM {
public static void main(String[] args) {
String str = "hello world";
while (true){
str += str + new Random().nextInt(99999999) + new Random().nextInt(9999999);
}
}
}