JVM快速入门

常见面试题:

  • 请谈谈你对JVM的理解,java8虚拟机和之前相比有哪些变化?
  • 什么是OOM,什么是栈溢出StackOverFlowError?怎么分析?
  • JVM的常用调优参数有哪些?
  • 内存快照如何抓取,怎么分析Dump文件?
  • 谈谈JVM中,你对类加载器的认识

JVM的体系结构

类加载

类加载器

类加载器作用:加载Class文件

package com.wang.jvm;

public class Car {
public int age;
public static void main(String[] args) {
//类是模板,对象是具体的

Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();

System.out.println(car1.hashCode());
System.out.println(car2.hashCode());
System.out.println(car3.hashCode());

Class<? extends Car> aClass1 = car1.getClass();
Class<? extends Car> aClass2 = car1.getClass();
Class<? extends Car> aClass3 = car1.getClass();

System.out.println(aClass1.hashCode());
System.out.println(aClass2.hashCode());
System.out.println(aClass3.hashCode());

}
}


1.虚拟机自带的加载器

2.启动类(根)加载器(Bootstrap classLoader)

3.扩展类加载器(ExtClassLoader)

4.应用程序加载器(AppClassLoader)

JavaSE学习(16)——JVM快速入门_加载器

package com.wang.jvm;

public class Car {
public int age;
public static void main(String[] args) {
//类是模板,对象是具体的

Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();

System.out.println(car1.hashCode());
System.out.println(car2.hashCode());
System.out.println(car3.hashCode());

Class<? extends Car> aClass1 = car1.getClass();

ClassLoader classLoader = aClass1.getClassLoader();
System.out.println(classLoader);// AppClassLoader 应用程序加载器
System.out.println(classLoader.getParent());// ExtClassLoader 扩展类加载器 \jre\lib\ext
System.out.println(classLoader.getParent().getParent());// null 1.不存在 2.java程序获取不到 rt.jar
}
}


JavaSE学习(16)——JVM快速入门_方法区_02

双亲委派机制

package java.lang;

public class String {
//双亲委派机制:保证安全
// APP->EXC->BOOT(最终执行)

public String toString(){
return "Hello";
}

public static void main(String[] args) {
String s = new String();
s.toString();
}
/*
1.类加载器收到类加载的请求
2.将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
3.启动加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,否则抛出异常,通知子加载器进行加载
4.重复步骤3
Class Not Found ~

null:java调用不到 C、C++
java(C++--):C++去掉繁琐的东西,指针,内存管理
*/
}


JavaSE学习(16)——JVM快速入门_方法区_03

沙箱安全机制

Java安全模型的核心就是Java沙箱(sandbox),沙箱是一个限制程序运行的环境。

沙箱机制就是将Java代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证代码的有效隔离,防止对本地系统造成破坏。

组成沙箱的基本组件:

  • 字节码校验器(bytecode verifier):确保Java类文件遵循Java语言规范(格式)。这样可以帮助Java程序实现内存保护。但并不是所有的类文件都会经过字节码校验,比如核心类(核心类已经测试过了,不需要再校验)
  • 类装载器(class loader):其中类装载器在3个方面对Java沙箱起作用
  • 它防止恶意代码去干涉善意的代码(双亲委派机制);
  • 它守护了被信任的类库边界;
  • 它将代码归入保护域,确定了代码可以进行哪些操作。

类装载器采用的机制是双亲委派模式。

1.从最内层JVM自带类加载器开始加载,外层恶意同名类得不到加载从而无法使用;

2.由于严格通过包来区分了访问域,外层恶意的类通过内置代码也无法获得权限访问到内层类,破坏代码就自然无法生效。

  • 存取控制器(access controller):存取控制器可以控制核心API对操作系统的存取权限,而这个控制的策略设定,可以由用户指定。
  • 安全管理器(security manager):是核心API和操作系统之间的主要接口。实现权限控制,比存取控制器优先级高。
  • 安全软件包(security package):java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:
  • 安全提供者
  • 消息摘要
  • 数字签名 keytools
  • 加密
  • 鉴别

Native

package com.wang.jvm;

public class Demo {
public static void main(String[] args) {
new Thread(()->{
},"my thread name").start();
}

private native void start0();
// native:凡是带了native关键字的,说明java的作用范围达不到了,回去调用底层c语言的库!
// 会进入本地方法栈
// 调用本地方法接口 JNI
// JNI作用:扩展Java的使用,融合不同的编程语言为Java所用!
// java诞生之初,C和C++横行,想要立足,必须要有调用C、C++的程序
// 所以在内存区域中专门开辟了一块标记区域:Native Method Stack(本地方法栈),登记native方法
// 在最终执行的时候,加载本地方法库中的方法通过JNI
// Java程序驱动打印机,管理系统,掌握即可,在企业级应用中较为少见

//调用其它接口:Socket,WebService~,http~
}


PC寄存器

程序计数器:Program Counter Register

每一个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

方法区

Method Area 方法区

方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,所有定义的方法的信息都保存在该区域,此区域属于共享空间

静态变量、常量、类信息(构造方法、接口定义)、运行时常量池存在方法区中,但是实例变量存在堆内存(将地址传给方法区)中,和方法区无关。

JavaSE学习(16)——JVM快速入门_java_04