文章目录
JVM
0 面试题
-
1、请你谈谈对JVM的理解
-
2、java8虚拟机和之前的变化更新?
-
3、什么是OOM,什么是栈溢出StackOverFlowError?怎么分析
-
4、JVM的常用调优参数有哪些?
-
5、内存快照如何抓取,怎么分析Dump文件?知道吗?
-
6、谈谈JVM中,类加载器你的认识?
rt-jar等 -
7、补充:new一个对象的内存分析
知识点
1、JVM的位置
2、JVM的体系结构(类的加载)
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。
堆——堆是所有线程共享的,主要用来存储对象。其中,堆可分为:年轻代和老年代两块区域。使用NewRatio参数来设定比例。对于年轻代,一个Eden区和两个Suvivor区,使用参数SuvivorRatio来设定大小;
Java虚拟机栈——线程私有的,主要存放局部变量表,操作数栈,动态链接和方法出口等;
本地方法栈:在内存区域中,专门开辟了一块标记区域(本地方法栈),登记native方法,会在最终执行的时候加载本地方法库中的本地方法。(详见第6节:Native)
程序计数器——同样是线程私有的,记录当前线程的行号指示器,为线程的切换提供保障;
方法区——线程共享的,主要存储类信息、常量池、静态变量、JIT编译后的代码等数据。方法区理论上来说是堆的逻辑组成部分;
运行时常量池——是方法区的一部分,用于存放编译期生成的各种字面量和符号引用;
3、类加载器
作用:加载Class文件
记住:类是模板,是抽象的,对象是具体的
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201201100733417.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1RoZXJhX3Fpbmc=,size_16,color_FFFFFF,t_70)
类加载器的分类
* 1、虚拟机自带的加载器
* 2、启动类(根)加载器
* 3、扩展类加载器
* 4、应用程序(系统)加载器:返回null,java调用不到,C、C++编写的
类加载有三种方式:
1、命令行启动应用时候由JVM初始化加载
2、通过Class.forName()方法动态加载
3、通过ClassLoader.loadClass()方法动态加载
```java
package JVM.ClassLoaderDemo;
/**
* @author ThetaQing
* 类加载器、双亲委派机制
*/
public class ClassLoaderTest {
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> car1Class = car1.getClass();
Class<? extends Car> car2Class = car2.getClass();
Class<? extends Car> car3Class = car3.getClass();
System.out.println(car1Class.hashCode());
System.out.println(car2Class.hashCode());
System.out.println(car3Class.hashCode());
ClassLoader classLoader = car1Class.getClassLoader();
// AppClassLoader
System.out.println(classLoader);
// ExtClassLoader 位置 ...\Java\jdk1.8.0_202\jre\lib\ext
System.out.println(classLoader.getParent());
// null java程序不能获取到的
System.out.println(classLoader.getParent().getParent());
}
}
class Car{
public int id;
}
```
类加载过程
4、双亲委派机制
作用:为了保障安全;
运行一个类之前,逐级类加载器向上找 1. AppClassLoader --> 2. EXC --> 3.BOOT,所以定义重名类是无效的。假设BOOT加载器中没有这个类,倒回去找扩展类加载器EXC,如果还没有回到APP类加载器。
过程:
* 1、 类加载器收到类加载的请求;
* 2、将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器;
* 3、启动类加载器检查是否能够加载当前这个类,能加载就结束,使用当前加载器,否则,抛出异常通知子加载器进行加载;
* 4、该加载器重复步骤3;
* 5、都找不到就报Class Not Found。
```java
package java.lang
public class String{
public String toString(){
return "hello";
}
public static void main(String[] args) {
String string = new String();
string.toString();
}
}
```
报错内容:java.lang.String中找不到main方法。
报错原因:根据双亲委派机制,最终调用的是BOOT中的String类
```java
public class Student{
@Override
public String toString(){
return "hello";
}
public static void main(String[] args) {
Student student= new Student();
student.toString();
}
}
```
正常运行
可以通过`student.getClass().getClassLoader()`进行确认是从哪个加载器中加载的。
5、java历史——沙箱安全机制(了解)
沙箱安全机制是什么:
> Java安全模型的核心就是Java沙箱(sandbox)。沙箱是一个限制程序运行的环境。沙箱机制就是讲Java代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。
沙箱主要限制系统资源访问,包括`CPU、内存、文件系统、网络`。
组成沙箱的基本组件:
> `字节码校验器(bytecode verifier)`:确保Java类文件遵循Java语言规范,帮助Java程序实现内存保护,但并不是所有的类文件都会经过字节码校验,