jvm相关

package com.xpf.jvm;

/**

  • @Author: Xia
  • @Date: 2020/4/27 15:10
  • @Email:x2358114512@163.com
  • 【上:类加载器相关】
    1. 什么是类加载器(Class Loader):
  • ClassLoader:负责加载class文件,class文件在文件开头有特定的文件标示(cafe babe),
  • 将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构并且ClassLoader
  • 只负责class文件的加载,至于它是否可以运行,则由Execution Engine(执行引擎)决定。
    1. ClassLoader的种类? 2. ClassLoader的每一种如何获取?
  • 一.虚拟机自带的加载器(ClassLoader)有
  • 1.启动类加载器(Bootstrap):java自带的类(Object、String等类)使用此加载器,C++语言编写的
  • 因为是c++编写,那么输出此类加载器时是nul值(代码验证),但是并不是代表其不存在
  • 2.扩展类加载器(Extension):java后期拓展的一些类(javax开头的包,x就是extension的意思)
  • 使用此加载器,Java语言编写的
  • 3.应用程序类加载器(AppClassLoader)Java也叫系统类加载器,
  • 加载当前应用的classpath的所有类:自己编写的类使用次加载器
  • 二.用户自定义加载器
  • Java.lang.ClassLoader(抽象类)的子类,用户可以定制类的加载方式
  • 3.双亲委派
  • 当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类的类加载器去完成,
  • 因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候
  • (在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。
  • 如果都没有就抛出ClassNotFound。
  • 采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,
  • 最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同样一个 Object对象。
  • 也就是我们写的类(代码)不能污染java自带的类(代码),保证了安全性。沙箱安全机制。
  • 4.沙箱安全机制
  • 【下:Execution Engine(执行引擎)】
  • Execution Engine(执行引擎):只要加载验证通过就可以执行,执行引擎负责解释命令,提交操作系统执行。
  • 【中:运行时数据区(Running Data Area)】
  • 1.Native Method Stack(本地方法栈)
  • 它的具体做法是Native Method Stack中登记native方法,在Execution Engine 执行时加载本地方法库。
  • native是关键字
  • 补充:Native Interface( 本地接口)
  • 本地接口的作用是融合不同的编程语言为 Java 所用,它的初衷是融合 C/C++程序,Java 诞生的时候是 C/C++横行的
  • 时候,要想立足,必须有调用 C/C++程序,于是就在内存中专门开辟了一块区域处理标记为native的代码,它的具体
  • 做法是 Native Method Stack中登记 native方法,在Execution Engine 执行时加载native libraies。
  • 目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机或者Java系统管理生产设备,
  • 在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用 Socket通信,也可以使用Web
  • Service等等,不多做介绍。
  • 2.PC寄存器(类似排班值日表,程序运行的顺序)
  • 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条
  • 指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略
  • 不记。 这块内存区域很小,它是当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要
  • 执行的字节码指令。
  • 注意:(1)、如果执行的是一个Native方法,那这个计数器是空的。
  • (2)、用以完成分支、循环、跳转、异常处理、线程恢复等基础功能。不会发生内存溢出(OutOfMemory=OOM)错误
  • 3.Method Area (方法区):最典型的就是永久代(PermGen space,1.7)和元空间(Metaspace,1.8)。
  • 供各线程共享的运行时内存区域(线程公有)。它存储了每一个类的结构信息(模板信息),
  • 例如运行时常量池(Runtime Constant Pool)、静态变量、虚拟机加载的类信息、即时编译后的代码。
  • 上面讲的是规范,在不同虚拟机里头实现是不一样的,最典型的就是永久代(PermGen space,1.7)和元空间(Metaspace,1.8)
  • 4.Java Stack(java栈)
  • 4.1 栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,
  • 线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,
  • 是线程私有的。
  • 注意: java栈空间中的包括: 8种基本类型的变量+对象的引用变量+实例方法
  • 4.2 栈帧中主要保存3类数据:
  • (1)本地变量(Local Variables):输入参数和输出参数以及方法内的变量;
  • (2)栈操作(Operand Stack):记录出栈、入栈的操作;
  • (3)栈帧数据(Frame Data):包括类文件、方法等等。
  • 4.3 每个方法执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,
  • 每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。栈的大小和具体
  • JVM的实现有关,通常在256K~756K之间,与等于1Mb左右。
  • 4.4 注意递归的结束条件不对:java.lang.StackOverflowError(这是个错误,不是异常)
  • 4.5 栈+堆+方法区的交互关系:如图收拾
  • HotSpot是使用指针的方式来访问对象:
  • Java堆中会存放访问类元数据(元数据:描述数据的数据,其实就是类模板数据)的地址,
  • reference存储的就直接是对象的地址
    1. Heap(堆)
  • 5.1 一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,
  • 需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行。
  • 5.2 堆内存分为三部分:
  • (1)堆内存逻辑上分为三部分:新生+养老+永久
  • (物理上永久代/元空间[方法区的实例化]不属于堆内存)
  • 5.2.1 Young Generation Space (新生区,Young/New,1/3)包括:
  • Eden Space、Survivor 0 Space、Survivor 1 Space[8:1:1]
  • 5.2.2 Tenure generation space (养老区,Old/ Tenure,2/3)
  • 5.2.3 Permanent Space (永久区,Perm)/Metaspace(元空间,Meta)
    */

class MyCode{

}
public class ClassLoaderDemo01 {
public static void main(String[] args) {
Object o = new Object();
System.out.println(o.getClass().getClassLoader()); //null值
// System.out.println(o.getClass().getClassLoader().getParent()); //报错:java.lang.NullPointerException

    MyCode myCode = new MyCode();
    System.out.println(myCode.getClass().getClassLoader());
    System.out.println(myCode.getClass().getClassLoader().getParent());
    System.out.println(myCode.getClass().getClassLoader().getParent().getParent());

// h1();
}
public static void h1(){
h1();
}
}

全部评论

相关推荐

11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务