深刻Java虚拟机之 -- 总结面试篇

本文已受权玉刚说公众号web

系列文章:面试

深刻Java虚拟机之 -- 总结面试篇算法

深刻Java虚拟机之 --- JVM的爱恨情仇安全

JAVA 垃圾回收机制(一) --- 对象回收与算法初识bash

JAVA 垃圾回收机制(二) --- GC回收具体实现app

深刻Java虚拟机之 -- 类文件结构(字节码)学习

深刻Java虚拟机之 -- 类加载机制ui

在学习 JVM 相关知识,怎么让本身有动力看下去,且有思考性呢?笔者认为,开头用一些经常使用的面试题,来引入读者的兴趣比较好,这样才会有看下去的东西,因此,该篇文章会以面试+总结的方式,但愿读者能先思考写出答案,再查看相关知识。spa

1、JVM常见面试题

深刻Java虚拟机之 -- 总结面试篇.net

  • 介绍下 Java 内存区域
  • Java 对象的建立过程
  • 对象的访问定位有几种
  • String、StringBuilder、StringBuffer 有什么不一样?

这是一些常见的面试,不少人都看到网上的标准答案,但你知道为何吗?

1.1 介绍下 Java 内存区域

首先看第一个,Java的内存区域,能够看一张编译图:

能够看到Java 的内存区域就是框框里的东西,每一步的大概意思以下,具体细节参考 深刻Java虚拟机之 --- JVM的爱恨情仇
在这里插入图片描述
总结,建议读者学习以后,能本身默写这些方法并指导每一步的意思;

1.2 Java 对象的建立过程

Java 对象的建立共分为5步,以下图:

在这里插入图片描述
而后明白每一个步骤作了哪些便可,以下:
在这里插入图片描述

1.三、对象的访问定位有几种

有两种方式:句柄和直接指针; 建立对象是为了使用对象,虚拟机须要经过栈中的 reference 来获取堆上的对象。

在这里插入图片描述
优缺点: 使用句柄好处是,当对象发生改变,只须要移动句柄的实例数据指针便可,而直接指针就是速度快。

1.4 String、StringBuilder、StringBuffer 有什么不一样

参考答案是: String 是用 final 修饰的类,因为它的不可变性,相似拼接、裁剪字符串等,都会产生新的对象。 StringBuffer 解决上面拼接对象而提供一个类,能够经过 append等方法拼接,是线程安全的,因为线程安全,效率也降低 StringBuilder 跟StringBuffer 差很少,只是去掉了线程安全,因此优先使用 StringBuilder

说说String 为何会产生新的对象?好比 String a = "1" String b = a + "2",当执行这条指令时,会在常量池中产生一个对象指向a,而建立b时也会从新在常量池中生成b的对象;屡次建立容易触发 GC,这也是为何不建议使用 String 类去拼接的问题。

2、Java 回收机制常见面试题

深刻Java虚拟机之 --- JVM的爱恨情仇 JAVA 垃圾回收机制(二) --- GC回收具体实现

  • 简单的介绍一下强引用、软引用、弱引用、虚引用(虚引用与软引用和弱引用的区别、使用软引用能带来的好处)
  • 谈谈final、finally、finalize 有什么不一样
  • 方法区会回收资源吗?
  • 垃圾回收有哪些算法,各自的特色?

2.1 简单的介绍一下强引用、软引用、弱引用、虚引用

首先,在讲解这几个引用以前,先明白虚拟机为何会由这些引用的说明;咱们都知道,对象须要回收,那怎么去判断哪些对象须要回收呢?这就须要一些判断来肯定哪些对象是须要回收的,通常有如下几种方法:

在这里插入图片描述
不管是 引用计算算法仍是可达性分析算法,都是涉及到对象的引用问题,因此,在 JDK1.2 以后,又分为如下几类引用:
在这里插入图片描述
经过上面的介绍,知道了" 引用"是什么关系,这对理解各类引用仍是颇有必要的,那么使用 软引用的好处也在那里了; 建议一些内存消耗较大的使用软引用,好比 webview。。

2.2 谈谈final、finally、finalize 有什么不一样

final 和finally 比较好理解。首先 final 用来修饰的对象不可变;finally 则是保证重点代码必定要被执行的一种机制,通常用于 try - catch-finally 语句中。 但finalize 是什么东西呢?在解释标准代码以前,又得回到GC算法中了。 首先,finalize 是 Object 的一个方法,用来特定资源的回收。 上面说到,当 GC Roots 不可达时,认为对象已经再也不使用了,可是对象并不是是非"死"不可,当 GC Roots 不可达时,系统首先会先判断 对象的 finalize 是否执行,不执行则直接回收;若是能够执行,则放在队列中,由finalize线程去执行它,若是有其余对象关联时,则判断对象不可回收,不然对象回收,finalize 执行一次,以下图:

在这里插入图片描述
因为它的不肯定性,在 JDK9时,已经标注为deprecated,但不影响咱们对它的理解。

2.3 方法区会回收资源吗?

虽然说 Java 堆 能够回收70%~95%的空间,但方法区一样能够回收一些资源,方法区主要回收两个部分废弃常量无用的类

在这里插入图片描述
因此,当发生 GC 时,很是常量和无用类是能够被回收,固然这里也是说"能够",是否像对象同样被回收,还须要对虚拟机的参数配置,这里就不细说了。

2.4 垃圾回收有哪些算法,各自的特色?

对象的回收,基于上面讲到的,GC Roots不可达,且判断能够回收。衍生的算法以下图(建议能默认每种算法的理解):

在这里插入图片描述
其中,基础是 标记-清除是基础,接下来都是在它的基础上改进,分代算法是主流 Java 虚拟机的主要算法; 其中各个算法特色以下,详细介绍看 JAVA 垃圾回收机制(一) --- 对象回收与算法初识 第四节,垃圾回收篇。
在这里插入图片描述
关系新生代和老年代的问题,参考: JAVA 垃圾回收机制(二) --- GC回收具体实现

3、类加载的问题

深刻Java虚拟机之 -- 类文件结构(字节码) 深刻Java虚拟机之 -- 类加载机制

  • 类加载过程
  • 写出下列代码打印信息,若将改为System.out.println(Child.c_value);改成System.out.println(Child.value); 如何?
public class Parent{
   static {
   	System.out.println("Parent");
   }
   public static int value = 123;
}

public class Child extends Parent{
   static {
   	System.out.println("Child");
   }
   public static int c_value = 123;
}

//mian 中执行
public static void main(String[] args) {
   System.out.println(Child.c_value);
}
复制代码
  • 说说你对类加载器的理解
  • 什么是双亲委派模型

3.1 类加载的过程

类加载的过程以下图所示(建议能默认每一个步骤的理解):

在这里插入图片描述
也能够成为 加载-链接-初始化 这种叫法。 其中, 加载、验证、准备、初始化和卸载的顺序是固定的,而解析则不必定,由于Java是动态语言,它能够在运行时解析,即初始化以后。该阶段解析以下:
在这里插入图片描述

3.2 写出下列代码打印信息,若将改为System.out.println(Child.c_value);改成System.out.println(Child.value); 如何?

public class Parent{
   static {
   	System.out.println("Parent");
   }
   public static int value = 123;
}

public class Child extends Parent{
   static {
   	System.out.println("Child");
   }
   public static int c_value = 123;
}

//mian 中执行
public static void main(String[] args) {
   System.out.println(Child.c_value);
}
复制代码

打印信息如:

Parent
Child
123
复制代码

改成System.out.println(Child.value)时:

Parent
123
复制代码

具体看:深刻Java虚拟机之 -- 类加载机制 扩展

class Parent{
		public static int value = 1;
		static {
			value = 2;
		}
	}
	
class Child extends Parent{

	public static int B = value ;
}


public static void main(String[] args) {
	System.out.println(Child.B);
}
复制代码

输出什么?

3.3 说说你对类加载器的理解

从上面咱们知道,类在加载的时候,就是经过一个全限定名去加载这个类的二进制字节流,这个是系统自动完成的。这个动做若是从外部去作,以便于咱们去获取所需的类,则咱们成为类加载器。好比经过一个路径获取到一个 class 字节码,而后经过反射,拿到相应的信息。

3.4 什么是双亲委派模型

它的工程流程是: 当一个类加载器收到类加载的请求,它首先不会本身去尝试加载这个类,而是委派给她的父类加载器去完成,每个层次的类加载器都是如此,所以全部的加载器都会传递到父加载器中;只有父加载器没法完成时,子加载器才会尝试本身去加载,它的模型以下:

类加载双亲委派模型
相关文章
相关标签/搜索