1. 说一下jvm的主要组成部分,及其作用?

    类加载器,执行引擎,本地库接口,运行时数据区

  2. 说一下jvm运行时数据区?

    jvm内存分为方法区,堆,虚拟机栈,本地方法栈,程序计数器。

  3. 说一下堆栈的区别?

    栈内存:栈内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。

    ​ 堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。

  4. 队列和栈是什么?有什么区别?

    队列(Queue):是限定只能在表的一端进行插入和另一端删除操作的线性表
    栈(Stack):是限定之能在表的一端进行插入和删除操作的线性表

    队列和栈的规则
    队列:先进先出
    栈:先进后出
    队列和栈的遍历数据速度
    队列:基于地址指针进行遍历,而且可以从头部或者尾部进行遍历,但不能同时遍历,无需开辟空间,因为在遍历的过程中不影响数据结构,所以遍历速度要快
    栈:只能从顶部取数据,也就是说最先进入栈底的,需要遍历整个栈才能取出来,遍历数据时需要微数据开辟临时空间,保持数据在遍历前的一致性

  5. 什么是双亲委派模式?

    类装载器请求另一个类装载器来装载类型的过程。

    在某个特定的类装载器试图以常用方式装载类型以前,它会先默认地将这个任务“委派”给它的双亲——请求它的双亲来装载这个类型。

    工作原理

    如果一个类加载器收到了类加载请求,它并不会自己去加载,而是把这个请求委托给父类的加载器去执行

    如果父类加载器还存在其父类加载器则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器

    采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。

    双亲委派机制的优势

    避免类的重复加载

    保护程序安全,防止核心 API 被随意篡改
    自定义类:java.lang.String
    自定义类:java.lang.ShkStart

  6. 说一下类加载的执行过程?

    三个主要步骤:加载,连接(验证,准备,解析),初始化

    首先是加载过程(Loading),它是 Java 将字节码数据从不同的数据源读取到 JVM 中,并映射为 JVM 认可的数据结构(Class 对象),这里的数据源可能是各种各样的形态,比如 jar 文件,class 文件,甚至是网络数据源等;如果输入数据不是 ClassFile 的结构,则会抛出 ClassFormatError。加载阶段是用户参与的阶段,我们可以自定义类加载器,去实现自己的类加载过程。

    ​ 第二阶段是连接(Linking),这是核心的步骤,简单说是把原始的类定义信息平滑地转入 JVM 运行的过程中。这里可进一步细分成三个步骤:1,验证(Verification),这是虚拟机安全的重要保障,JVM 需要核验字节信息是符合 Java 虚拟机规范的,否则就被认为是 VerifyError,这样就防止了恶意信息或者不合规信息危害 JVM 的运行,验证阶段有可能触发更多 class 的加载。2,准备(Pereparation),创建类或者接口中的静态变量,并初始化静态变量的初始值。但这里的“初始化”和下面的显示初始化阶段是有区别的,侧重点在于分配所需要的内存空间,不会去执行更进一步的 JVM 指令。3,解析(Resolution),在这一步会将常量池中的符号引用(symbolic reference)替换为直接引用。在 Java 虚拟机规范中,详细介绍了类,接口,方法和字段等各方面的解析。

    ​ 最后是初始化阶段(initialization),这一步真正去执行类初始化的代码逻辑,包括静态字段赋值的动作,以及执行类定义中的静态初始化块内的逻辑,编译器在编译阶段就会把这部分逻辑整理好,父类型的初始化逻辑优先于当前类型的逻辑。再来谈谈双亲委派模型,简单说就是当加载器(Class-Loader)试图加载某个类型的时候,除非父类加载器找不到相应类型,否则尽量将这个任务代理给当前加载器的父加载器去做。使用委派模型的目的是避免重复加载 Java 类型。

  7. 怎么判断对象是否可以被回收?

    当一个对象的地址没有变量去引用时,该对象就会成为垃圾对象,垃圾回收器在空闲的时候会对其进行内存清理回收

    如何检验对象是否被回收?
    可以重写 Object 类中的 finalize 方法,这个方法在垃圾收集器执行的时候,被收集器自动调用执行的

    怎样通知垃圾收集器回收对象?
    可以调用 System 类的静态方法 gc(),通知垃圾收集器去清理垃圾,但不能保证收集动作立即执行,具体的执行时间取决于垃圾收集的算法

  8. Java中都有哪些引用类型?

    强引用:只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象实例。

    软引用:是用来描述一些还有用但并非必需的对象。

    弱引用:也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱 引用关联的对象实例只能生存到下 一次垃圾收集发生之前。

    虚引用:在任何时候都可能被垃圾回收。虚引用必须和引用队列( ReferenceQueue )联合使用 。把这个虚 引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解 被引用的对象是否将要被垃圾回收。

  9. 说一下jvm有哪些垃圾回收算法?
  10. 说一下jvm有哪些垃圾回收器?
  11. 详细介绍一下CMS垃圾回收器?
  12. 新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
  13. 简述分代垃圾回收器是怎么工作的?
  14. 说一下jvm调优的工具?
  15. 常用的jvm调优的参数都有哪些?