JVM&&GC
1.JVM概述
什么是虚拟机?
- 虚拟机:模拟某种计算机体系结构,特殊特定指令集的软件。
- 分为两大类:
- 系统虚拟机(Virtual Box,VMware);
- 程序虚拟机(JVM,NET CLR,P-Code)
什么是Java虚拟机
Java虚拟机架构
-
1,程序计数器:指向当前线程正在执行的字节码的地址,行号。线程
私有,无GC。 -
2,虚拟机栈:存储当前线程运行方法所需要的数据,指令,返回地
址。线程私有,无GC。 -
3,本地方法栈:同虚拟机栈,不同的是,它存的是本地方法的数据。
-
4,方法区:存储类信息(字段方法的字节码,部分方法的构造器),常
量,静态变量,JIT(即时编译的信息)。线程共享,无GC,非堆区。
java.lang.OutOfMemoryError: PermGen space) -
5,堆-heap: 存储类实例,-个jvm实例只有一个堆内存。线程共享,
要GC。 -
Jdk1.6及之前:有永久代字符串常量池和运行时常量池在方法区
-
Jdk1.7:有永久代, 但已经逐步“去永久代”,字符串常量池移到堆
中,运行时常量池还在方法区中(永久带) -
Jdk1.8及之后:无永久代,字符串常量池在堆中,运行时常量池在元
空间 -
方法区是一种定义,概念。而所谓永久代或元空间是其一种实现机制。
Hostpot虚拟机
共有设计,私有实现
2.类加载
类加载器
- -verbose:class:显示类加载过程(在VM option中填写)
/**
* 三个类加载器
* 1.引导(启动)类加载器
* 2.扩展类记载器
* 3.系统类加载器
*/
public class Main {
public static void main(String[] args) {
//获取系统类加载器
//1.ClassLoader.getSystemClassLoader();
ClassLoader appClassLoader1 = ClassLoader.getSystemClassLoader();
//2.
ClassLoader appClassLoader2 = Main.class.getClassLoader();
System.out.println(appClassLoader1.toString());
System.out.println(appClassLoader2.toString());
//获取扩展类加载器
ClassLoader extentClassLoader = appClassLoader1.getParent();
System.out.println(extentClassLoader.toString());
ClassLoader extClassLoader = SunEC.class.getClassLoader();
System.out.println(extClassLoader.toString());
//启动类加载器(c语言实现的,看不见)extClassLoader.getParent()为空
//,加toString,会空指针异常
System.out.println(extClassLoader.getParent());//null
}
}
类加载过程
面试题
public class Main {
public static void main(String[] args) {
//第一题 0 1 2
//第二题 0 2 3
System.out.println(T.count);
}
}
class T{
private static T t = new T();
public static int count=2;
private T(){
count++;
}
}
双亲委托机制
package java.lang;
public class String {
public static void main(String[] args) {
System.out.println("java.lang.String.");
}
}
错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application
package java.lang;
public class MyString {
public static void main(String[] args) {
System.out.println("java.lang.MyString");
}
}
java.lang.SecurityException: Prohibited package name: java.lang
- 向上委托后,在向下委托,都干不了,又ApplicationClassLoader加载,但是不能使用,java.lang包,所以报错。
使用类加载器夹杂属性文件
public class Main {
public static void main(String[] args) throws IOException {
//src :source文件生成.class文件 打包完就没这个目录了。
//使用类加载器加载属性文件
//获取的是项目根目录
//建议使用
InputStream is = Main.class.getClassLoader().getResourceAsStream("user.properties");
//以当前目录为指针写文件,如果不在本目录同一层使用/com/demodong....
// /com/demodong 中的 /为根目录。
// Main.class.getResourceAsStream()
Properties properties = new Properties();
// FileInputStream fis = new FileInputStream("src\\user.properties");
properties.load(is);
// fis.close();
is.close();
properties.list(System.out);
}
}
运行jar包:java -jar xx.jar
3.运行时数据区
概念
程序计数器
虚拟机栈和本地方法栈
栈帧
- 栈帧包含
- 1.局部变量表,
- 2.操作数栈
- 3.动态连接
- 4.方法返回地址。
栈帧结构-局部变量表
栈帧结构-操作数栈
Demo
栈帧结构-动态连接
栈帧结构-方法返回地址
堆
System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024); //1/64
System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);
System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024); // 1/4
-Xms10m -Xmx10m
简单查看栈溢出
public class Main {
public static void main(String[] args) throws InterruptedException {
byte []buffer=new byte[1024*1024*7];
buffer=null;
Thread.sleep(1000);
}
/**
* 栈帧:
* 1.局部变量表
* 2.操作数栈
* 3.动态连接
* 4.返回地址。
*/
}
设置虚拟机的大小
- 首先轻度GC进行两次垃圾回收,不行了使用重度GC进行搞。
- 空的为to。
- 阀值为15放进老年代。
-
- 年轻代(Young generation)
- 伊甸园(Eden)
- 幸存区(Survivor Scope)
- from
- to (空的为to)
- 老年代(Old generation)
堆-对象分配策略
Java对象
方法区
运行时常量池
HotSpot方法区实现的变迁
直接内存
其他空间
逃逸分析
4.垃圾判断
什么是垃圾回收
垃圾判定
引用计数算法
可达性分析算法
Root对象
Java对象引用
finalization
5.垃圾回收算法
java的垃圾回收
常用的垃圾回收算法
标记-清除算法(Mark-Sweep)
标记-整理算法(Mark -Compact))
复制算法(Copying)
分代收集算法
6.垃圾收集器
Serial收集器(串行收集器)
ParNew收集器
Parallel Scavenge收集器
Serial Old 收集器
Parallel Old收集器
CMS收集器