JVM基础知识1---尚硅谷视频笔记整理

JVM的知识

  1. JVM的体系结构
    总体分为三个部分,从上到下,依次是:类加载器,运行时数据区,执行引擎和本地方法接口。其中最重要的部分是运行时数据区,该区包括:方法区,堆,java栈,本地方法栈,程序计数器。其整体架构如图所示:

运行时数据区中暗色部分代表线程私有,占用内存少;亮色部分则是可以被线程共享的,且存在垃圾回收。
2. 类加载器
掌握的三个要点:
(1) 有哪几种类加载器
(2) 双亲委托机制
(3) 沙箱安全机制
作用:负责加载class文件,class文件在文件开头有特定的文件标示,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine(执行引擎)决定。

通俗解释:ClassLoader就相当于快递员,因此,可以有多种类加载器

  1. 具体的类加载器
    λ 虚拟机自带的加载器
    λ 启动类加载器(Bootstrap)C++
    λ 扩展类加载器(Eextension)java
    λ 应用程序类加载器(AppClass)
    java也叫系统类加载器,加载前应用的classpath的所有类

λ 用户自定义加载器
java.lang.ClassLoader的子类,用户可以定制类的加载方式

public class MyObject {
public static void main(String[] args) {
//Object类是JDK自带的类,加载它用的是Bootstrap启动类加载器,但是该类是c++写的,因此用getClassLoader()获得的是null
Object object=new Object(); System.out.println(object.getClass().getClassLoader());
// MyObject类是自己定义的,使用的是AppClassLoader应用程序加载器
Object myobject=new MyObject(); System.out.println(myobject.getClass().getClassLoader());
}
}
运行结果:
null
jdk.internal.loader.ClassLoaders$AppClassLoader@3d4eac69

类加载器的继承结构:

public class MyObject {
public static void main(String[] args) {
Object myobject=new MyObject(); System.out.println(myobject.getClass().getClassLoader().getParent().getParent()); System.out.println(myobject.getClass().getClassLoader().getParent()); System.out.println(myobject.getClass().getClassLoader());
}
}
运行结果:
//自定义类的父亲的父亲的加载器就是启动类加载器
null
//自定义类的父亲的加载器就是扩展类加载器

jdk.internal.loader.ClassLoaders P l a t f o r m C l a s s L o a d e r @ 38 a f 3868 / / 自 定 义 类 的 加 载 器 就 是 应 用 程 序 类 加 载 器 j d k . i n t e r n a l . l o a d e r . C l a s s L o a d e r s PlatformClassLoader@38af3868 //自定义类的加载器就是应用程序类加载器 jdk.internal.loader.ClassLoaders PlatformClassLoader@38af3868//jdk.internal.loader.ClassLoadersAppClassLoader@3d4eac69

4 类加载器的双亲委托机制和沙箱安全机制
当一个类收到了类加载请求,它首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载器中,只有当父类加载器反馈自己无法完成这个请求的时候(再它的加载路径下没有找到所需加载的class),子类加载器才会尝试自己去加载。
采用双亲委派的一个好处是比如加载位于rt.jar包中的类java.lang.Object,不管是哪个加载器加载这个类,最后都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载最终得到的都是同样一个Object对象。

5执行引擎负责解释命令,提交操作系统执行
6 Native Interface本地接口
本地接口的作用是融合不同的编程语言为java所用。Java诞生的时候是c/c++横行的时候,要想立足,必须有调用c/c++程序,于是就在内存中专门开辟了一块区域处理标记为native的代码,它的具体做法是Native Method Stack中登记native方法,再Execution Engine执行时加载native libraries.
Native Method Stack本地方法栈:
在Native Method Stack中登记native方法,在Execution Engine执行时加载本地方法。
7 程序计数器
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也就是即将要执行的指定代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。
这块内存区域很小,它是当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令。
如果执行的是一个Native方法,那这个计数器是空的。
用以完成分支,循环,跳转,异常处理,线程回复等基础功能。不会发生内存溢出(OutOfMemory=OOM)错误。
通俗解释:
PC寄存器记录了方法之间的调用和执行情况,类似排班值日表,用来存储指向下一条指令的地址,也就是即将要执行的指令代码,它是当前线程所执行的字节码的行号指示器。

8 方法区
供各线程共享的运行时内存区域,它存储了每一个类的结构信息(模板),例如,运行时常量池(Runtime Constant Pool),字段和方法数据,构造函数和普通方法的字节码内容。上面讲的是规范,在不同的虚拟机里实现是不一样的,最典型的就是永久代(PermGen space)和元空间。
空调 k1=new 格力();
List list=new ArrayList();
方法区 f =new 永久代;
方法区 f =new 元空间;
但是,实例变量存在堆内存中,和方法区无关。

文章内容来自于尚硅谷视频的笔记整理,如有侵权,联系删除

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值