Notes about JVM
不得不说,特么这兄弟归纳的太好了
字符串常量池
内存结构
上面的线程共享区,因为所有对象都在这里分配内存,所以也是GC的主要区域
关于堆结构,上图是JDK8的示意图 ###堆
新生代:
所有新生成的对象首先都是存放在新生代
Eden区
最主要包含了刚创建的对象,该区域对象大部分都是短期内死亡,所以垃圾回收器主要用标记-整理算法回收该区域
Survivor区
又分为平等的两个区:
- From Survivor(s0)
- To Survivor(S1) 采用复制算法,每次只使用其中一块;
Eden:Survivor=8:1
老年代
一般在Survivor中没有被清除出去的对象才会进入该区域,主要使用标记-清除(mark-sweep)算法
操作
可-Xms 数字或-Xmx 数字 两个jvm参数来指定一个程序的堆内存大小,第一个是起始值,第二个是最大值
java -Xms1M -Xmx2M helloworld
方法区(method area)
用于存放已被加载的类信息,常量,静态变量,即时编译器编译(jit)后的代码等 然而对其进行垃圾回收的话主要是对常量池和类的卸载
Hotspot虚拟机把它当作永久代进行垃圾回收,但因为很少确定永久代的大小 JDK1.8开始,把永久代移除,并把方法区移至元空间(位于本地内存,不是JVM内存)
运行时常量池
是方法区一部分,Class文件中的常量池(编译器生成的各种字面量和符号引用)会在类加载后被放入这个区域 除了在编译期生成的常量,还允许动态生成,如string.Intern() PS:
- 用双引号声明出来的String对象会被存储在常量池里
- 如果不是用双引号,intern方法会从字符串常量池中查询字符串是否存在,如果不存在就会将当前字符串放入常量池
常见面试题
String s=new String("abc");
如上创建了多少个对象? 答案就是2个,一个是String在堆上的对象,一个是常量池里面的字符串”abc“
操作
-XX:PermSize最小空间 -XX:MaxPermSize最大空间
异常
和heap一样不需要连续的内存,而且动态扩展,失败会抛出OutOfMemory异常
JVM stack
每个Java方法在执行的同时会创建一个栈帧用于存储局部变量表,操作数栈,常量池引用等信息; 从调用到执行完成的过程,就对应了一个栈帧在jvm栈中的入栈和出栈
操作
可以通过 -Xss 设置jvm栈大小
java -Xss512M helloworld
异常
当请求栈深度超过最大值,会抛出stackoverflow异常
本地方法栈
本地方法栈与JVM栈类似,只不过JVM栈为java方法(字节码)服务,本地方法为JVM的native方法服务 本地方法一般由c++,汇编等编写
操作
Sun jdk中和jvm栈和本地方法栈是同一个,因此也可以用-Xss控制每个线程的大小
程序计数器
记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空)
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!