1.2019年周阳老师JVM·第一部分

文章目录

  • JVM架构图
    • JVM体系结构概述
  • 类装载器
    • 类加载器都有哪些?
    • 双亲委派机制
  • 本地接口
  • pc寄存器
  • 小总结

JVM架构图

常见的虚拟机面试题:主要是考淘宝的大神周志明写的那本书
1.2019年周阳老师JVM·第一部分_第1张图片

JVM体系结构概述

1.2019年周阳老师JVM·第一部分_第2张图片
扩展:JNI–java调用底层硬件,android还在用。
1.2019年周阳老师JVM·第一部分_第3张图片
对于这张图,做一个知识链接,runtimeException是从运行时数据区抛出来的。

类装载器

1.2019年周阳老师JVM·第一部分_第4张图片
方法区:放类的描述信息,就是放模板的地方。
classLoader有多种(粗说三个,细说四个,下面介绍)。类装载器之前是class(小写),装载之后是Class。也就是下面这个类。
1.2019年周阳老师JVM·第一部分_第5张图片
特定的文件标示是java的图标:cafe babe
1.2019年周阳老师JVM·第一部分_第6张图片

类加载器都有哪些?

1.2019年周阳老师JVM·第一部分_第7张图片
1.2019年周阳老师JVM·第一部分_第8张图片
系统自带的类,比如object,打印类加载器是null,实际上自带的类是被bootstrap classload加载的,但是你打印不出来。bootstrapclassloader是顶级的类加载器,不再有父类了。所有你一安装jdk就能用的,都是由bootstapclassloader加载。是安装路径lib目录下的rt.jar,也就是runtime.jar,运行时需要的jar包。可以打开rt.jar看一下,如下:
1.2019年周阳老师JVM·第一部分_第9张图片
1.2019年周阳老师JVM·第一部分_第10张图片
如果是自己编写的类,走的是appclassloader这个加载器。
扩展类加载器extentionclassloader,加载的是javax开头的包:
1.2019年周阳老师JVM·第一部分_第11张图片
1.2019年周阳老师JVM·第一部分_第12张图片
怎么理解呢?rt.jar中装载的是基础功能,ext文件夹下的jar包是扩展功能(如上图)。

1.2019年周阳老师JVM·第一部分_第13张图片
在这里插入图片描述
刚才appclassloader前面有个类前缀(上2图),这个类是jvm相关调用的入口程序。
可以根据类加载器的继承关系,打印出下图中的内容。
1.2019年周阳老师JVM·第一部分_第14张图片
1.2019年周阳老师JVM·第一部分_第15张图片
在这里插入图片描述
根据这个实验我们可以看出类加载器是有继承关系的。
可以关注的是classloader是一个抽象类,必须被继承,如下:
1.2019年周阳老师JVM·第一部分_第16张图片
就是通过这个抽象类来自定义类加载器。

双亲委派机制

类加载的考点:有哪几种类加载器?什么是classloader类加载器的双亲委派机制?沙箱安全机制?
双亲委派机制:我爸是李刚,有事找我爹!根据类加载器的继承结构,找一个类先从爷爷辈类加载器(bootstrapclassloader)往下找,一直找到孙子辈。也就是下图:
1.2019年周阳老师JVM·第一部分_第17张图片
找到最下方找不到就会报错:class not found exception。
如果出现包名+类名与java自带的重合,如下图,会发生什么事呢?
1.2019年周阳老师JVM·第一部分_第18张图片
结果是会运行失败:
1.2019年周阳老师JVM·第一部分_第19张图片
个人理解:就因为双亲委派机制,在bootstrapclassloader类加载器这一层,就找到了String这个类,并进行了加载,但是jdk自带的String类,并没有main函数,所以出现了上图的报错。双亲委派机制就是往上捅

也就是为了用户写的代码,不污染原厂自带的代码,提供了双亲委派机制来保证沙箱安全。保证大家使用不同的类加载器加载的String都是同一个。先找到,先使用,后面的不考虑。
1.2019年周阳老师JVM·第一部分_第20张图片
执行引擎没啥好说,加载完了就执行就ok了。
在这里插入图片描述

本地接口

1.2019年周阳老师JVM·第一部分_第21张图片
1.2019年周阳老师JVM·第一部分_第22张图片
我们平时所说的堆栈,指的是java栈(new出来的对象的引用放于此),而不是本地方法栈。
以线程Thread的start类引入:java的多线程是跟操作系统有关系(进程和线程是操作系统的概念)。
1.2019年周阳老师JVM·第一部分_第23张图片
实际上底层是调用的start0这个方法。
这里补充一下线程的6种状态:
Java中的线程的状态分为6种。

  • 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
  • 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的成为“运行”。
    线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得cpu 时间片后变为运行中状态(running)。
  • 阻塞(BLOCKED):表线程阻塞于锁。
  • 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
  • 超时等待(TIME_WAITING):该状态不同于WAITING,它可以在指定的时间内自行返回。
  • 终止(TERMINATED):表示该线程已经执行完毕。
    知识链接:http://www.zhiliaotang.net/jishujiaoliu/java/249.html
    如果一个线程启动2次,则会报错。如下:
    1.2019年周阳老师JVM·第一部分_第24张图片
    因为源码里面线程的状态不对,在启动的时候就会抛出异常:
    1.2019年周阳老师JVM·第一部分_第25张图片
    关注一下start0方法:native修饰,只有方法声明,没有方法的实现。
    在这里插入图片描述
    用native修饰的方法,调用的事操作系统的函数或者c语言函数库的功能,不是java本身的功能。
    如果是native方法就放在native栈(native方法专用)里面,因为他不是java具体实现的方法,不应该放在方法栈。
    1.2019年周阳老师JVM·第一部分_第26张图片
    native方法的具体实现交给了底层的第三方函数库。这是早期java调用c留的一种接口。
    总结:
    1.2019年周阳老师JVM·第一部分_第27张图片

pc寄存器

1.2019年周阳老师JVM·第一部分_第28张图片
register:寄存器,CPU里的一小块空间。
pc寄存器就是一个指针,指着这个方法运行完了之后,下一个方法是谁。
1.2019年周阳老师JVM·第一部分_第29张图片
pc寄存器:线程私有,内存占用很少,几乎不存在垃圾回收。

小总结

1.2019年周阳老师JVM·第一部分_第30张图片
为什么要有双亲委派机制:因为要沙箱安全,保证调用的基础的类都是同一个。保护原生类,防止被污染。

在这里插入图片描述
在这里插入图片描述

你可能感兴趣的:(Java虚拟机)