Java基础相关

JVM 面试必备(上)

2020-05-05  本文已影响0人  Sincerity_

JVM的组成

  1. 类加载器 在jvm启动时或者类运行将需要的Class加载到JVM中

  2. 执行引擎 负责执行Class文件中包含的字节码指令

  3. 内存区 (运行时数据区) 是JVM运行的时候操作所分配的内存区,运行时内存区主要分为

    1. 方法区: 用于存储类结构信息 包含常量池 静态常量 构造函数 运行时常量池

    2. java堆 存储java实例或者对象的地方,GC的主要区域

    3. java栈 和线程相关 每创建一个线程,jvm就会为这个线程创建一个对应的java栈,其中包含多个栈帧,每运行一个方法就是建一个栈帧,用于存储局部变量表, 操作栈 方法返回等,

    4. 程序计数器 用于保存当前线程执行的内存地址 由于JVM程序是多线程,所以保证线程切换回来,就需要单独的程序计数器记录之前中断的地方,

    5. 本地方法栈 和java栈差不多,不过为jvm的native方法服务

  4. 本地方法接口 主要调用C/C++ 实现本地方法以及回调结果

GC的原理和回收策略

java四种引用类型:

可达性算法

可达性算法通过一系列称为GCRoots的对象作为起始点,这些节点向下搜索,所走过的路径称为引用链,当一个对象没有任何引用链存与GCRoots链接时说明这个对象不可达,(不可用)

可达性算法流程
垃圾回收算法
Java堆内存

内存分配和回收策略

类加载器

类加载器
双亲委托机制

类加载器可以分为三类

  1. 启动类加载器: 负责加载<Java_Home>\bin目录下或者被-XbootClassPath参数指定的路径.并且是被虚拟机识别的库到内存中

  2. 拓展类加载器: 负责加载<Java_home>\bin\ext 目录下或者被java.ext.dirs 系统变量所指定的路径的所有内加载到内存中

  3. 应用类加载器 : 负责加载用户类路径上的指定类库,如果应用程序中没有实现自己的加载类,一般就是这个类去加载应用程序中的类库

原理

ClassLoader 使用的是双亲委托模式来搜索类.每个CLassLoder实例都有一个父类加载器的引用,(不是继承关系 是包含的关系) 虚拟机内置的类加载器,(Bottstrap classLoder) 本身没有父类加载器,但是可以作用其它ClassLoder实例的父类加载器

当一个ClassLoder实例需要加载某个类的时候,它会试图搜索某个之前,它这个任务委托给它的父类加载器,这个过程由上至下一次检查,首先由最顶层的bootStrapClassLoder尝试加载,如果没有加载成功,则会把任务转交给ExtensionClassLoder试图加载,吐过没有加载到,则转交给AppClassLoder进行加载,如果它也没有加载到的话,就会转交给委托的发起者,由它指定的问价系统或者网络等待URL中加载该类 如果他们都没有加载到这个类,就会抛出ClassNotFoundException异常

类加载机制

类的加载值得是将类的.class文件中的二进制数据读取到内存中,将其放在运行时数据区的方法区内,然后在堆中创建创建一个java.lang.class对象,用来封装在方法区内的数据结构,类的加载最终是在堆区的Class对象,Class对象封装了类在方法区内的数据结构,并且向外界提供访问方法区内数据结构的接口

类加载有三种方式

  1. 命令行启动应用时候由JVM初始化加载

  2. 通过Class.forName()方法动态加载

  3. 通过ClassLoder.loadClass()动态加载

如果一个类加载器收到加载类的请求,它不会自己去加载这个类,它会先请求父类加载器,每层的加载器都是如此,层层传递,直到传递到最高层的类加载器,只有父类加载器反馈无法加载此类时才会让子类加载器去加载该类

双亲委托模式的优点

避免重复加载 当父类加载该类,就没有必要让子类再加载一次

jvm搜索类的时候 如何判断二个Class是相同的呢?

JVM在判定二个类是否相同 ,不仅要判断二个类名相同,而且要判断是否同一个类加载器实例加载,只有二者满足时JVM才会认为这二个Class是相同的

Android 类加载器

在Android系统中 最终的APK文件包含的dex类型的文件,dex文件是将Class文件重新打包,打包的规则是将Class文件内部的各种函数表进行优化,产生一个新文件,即是Dex文件,因此加载某种特殊的Class文件就需要特殊的类加载器DexClassLoder

可以动态加载Jar通过URLClassLoder

  1. ClassLoder 隔离问题 JVM识别一个类是由 ClassLoderId +packageName+ClassName

  2. 加载不同Jar包的公共类

    1. 让父类ClassLoder加载公共的jar 子类ClassLoder加载包含公共jar的jar 此时子类ClassLoder在加载jar时会先去父类加载ClassLoder中

    2. 重写加载包含jar的jar的classLoder 在Class中找到已经加载过公共jar的classLoder 是吧父类classLoder替换掉

    3. 生成包含公共jar的jar时候把公共jar去掉

java虚拟机的栈内存和堆内存

上一篇下一篇

猜你喜欢

热点阅读