前言
聊聊JVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别。
JVM可以说和我们是老朋友了,但是在工作中的应用场景也许不如那些框架,但是在关键时候还是得靠它去搞定问题,俗话说得好,知己知彼,方能百战不殆,JVM作为前往高级工程师的一道坎,从这篇文章开始,我们会去逐步的分析,讲解,攻克这座大山。
有关Java虚拟机类加载机制相关的文章一搜一大把,就也不必再赘述一遍了。在这里捞出一道code题要各位大佬来把玩把玩,如果你一眼就看出了端倪,那么恭喜你,你可以下山了:
问题:请问这段程序的输出是什么?
一般对于这类问题,小伙伴们脑海中肯定浮现出这样的知识点
Java中赋值顺序:
  • 父类的静态变量赋值
  • 自身的静态变量赋值
  • 父类成员变量赋值和父类块赋值
  • 父类构造函数赋值
  • 自身成员变量赋值和自身块赋值
  • 自身构造函数赋值
按照这个理论输出是什么呢?
答案输出:1 4,这样正确嚒?
肯定不正确啦,这里不是说上面的规则不正确,而是说不能简单的套用这个规则。正确的答案是:
有没有答对呢?这里主要的点之一:实例初始化不一定要在类初始化结束之后才开始初始化。类的生命周期是:加载->验证->准备->解析->初始化->使用->卸载,只有在准备阶段和初始化阶段才会涉及类变量的初始化和赋值,因此只针对这两个阶段进行分析;
类的准备阶段需要做是为类变量分配内存并设置默认值,因此类变量st为null、b为0;(需要注意的是如果类变量是final,编译时javac将会为value生成ConstantValue属性,在准备阶段虚拟机就会根据ConstantValue的设置将变量设置为指定的值,如果这里这么定义:static final int b=112,那么在准备阶段b的值就是112,而不再是0了。)
类的初始化阶段需要做的是执行类构造器(类构造器是编译器收集所有静态语句块和类变量的赋值语句按语句在源码中的顺序合并生成类构造器,对象的构造方法是(),类的构造方法是(),可以在堆栈信息中看到),因此先执行第一条静态变量的赋值语句即st = new StaticTest (),此时会进行对象的初始化,对象的初始化是先初始化成员变量再执行构造方法,因此打印2->设置a为110->执行构造方法(打印3,此时a已经赋值为110,但是b只是设置了默认值0,并未完成赋值动作),等对象的初始化完成后继续执行之前的类构造器的语句,接下来就不详细说了,按照语句在源码中的顺序执行即可。
这里面还牵涉到一个冷知识,就是在嵌套初始化时有一个特别的逻辑。特别是内嵌的这个变量恰好是个静态成员,而且是本类的实例。这会导致一个有趣的现象:“实例初始化竟然出现在静态初始化之前”。其实并没有提前,你要知道java记录初始化与否的时机。看一个简化的代码,把关键问题解释清楚:
根据上面的代码,有以下步骤:
  • 首先在执行此段代码时,首先由main方法的调用触发静态初始化。
  • 在初始化Test 类的静态部分时,遇到st这个成员。
  • 但凑巧这个变量引用的是本类的实例。
  • 那么问题来了,此时静态初始化过程还没完成就要初始化实例部分了。是这样么?
  • 从人的角度是的。但从java的角度,一旦开始初始化静态部分,无论是否完成,后续都不会再重新触发静态初始化流程了。
  • 因此在实例化st变量时,实际上是把实例初始化嵌入到了静态初始化流程中,并且在楼主的问题中,嵌入到了静态初始化的起始位置。这就导致了实例初始化完全至于静态初始化之前。这也是导致a有值b没值的原因。
  • 最后再考虑到文本顺序,结果就显而易见了。
详细看到这里,心中大概有个结论了吧。
 
 
这是20道面试官经常问的JVM面试题,看一看你会几道?
1. 内存模型以及分区,需要详细到每个区放什么。
2. 堆里面的分区:Eden,survival (from+ to),老年代,各自的特点。
3. 对象创建方法,对象的内存分配,对象的访问定位。
4. GC 的两种判定方法:
5. SafePoint 是什么
6. GC 的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?
7. GC 收集器有哪些?CMS 收集器与 G1 收集器的特点。
8. Minor GC 与 Full GC 分别在什么时候发生?
9. 几种常用的内存调试工具:jmap、jstack、jconsole、jhat
10. 类加载的几个过程:
11.JVM 内存分哪几个区,每个区的作用是什么?
12.如和判断一个对象是否存活?(或者 GC 对象的判定方法)
13.简述 java 垃圾回收机制?
14.java 中垃圾收集的方法有哪些?
15.java 内存模型
16.java 类加载过程?
17. 简述 java 类加载机制?
18. 类加载器双亲委派模型机制?
19.什么是类加载器,类加载器有哪些?
20.简述 java 内存分配与回收策率以及 Minor GC 和Major GC
 
 
 

这道面试必问的JVM面试题70%的Java程序员会做错的更多相关文章

  1. 面试必问:JVM类加载机制详细解析

    前言 在Java面试中,简历上有写JVM(Java虚拟机)相关的东西,JVM的类加载机制基本是面试必问的知识点. 类的加载和卸载 JVM是虚拟机的一种,它的指令集语言是字节码,字节码构成的文件是cla ...

  2. 面试必问之JVM篇

    前言 只有光头才能变强 JVM在准备面试的时候就有看了,一直没时间写笔记.现在到了一家公司实习,闲的时候就写写,刷刷JVM博客,刷刷电子书. 学习JVM的目的也很简单: 能够知道JVM是什么,为我们干 ...

  3. 大厂必问的JVM面试题

    本文目录: 讲一下JVM内存结构? 程序计数器 虚拟机栈 本地方法栈 堆 方法区 运行时常量池 直接内存 Java对象的定位方式 说一下堆栈的区别? 什么情况下会发生栈溢出? 类文件结构 什么是类加载 ...

  4. 一线大厂Java面试必问的2大类Tomcat调优

    一.前言 最近整理了 Tomcat 调优这块,基本上面试必问,于是就花了点时间去搜集一下 Tomcat 调优都调了些什么,先记录一下调优手段,更多详细的原理和实现以后用到时候再来补充记录,下面就来介绍 ...

  5. 高级测试工程师面试必问面试基础整理——python基础(一)(首发公众号:子安之路)

    现在深圳市场行情,高级测试工程师因为都需要对编程语言有较高的要求,但是大部分又没有python笔试机试题,所以面试必问python基础,这里我整理一下python基本概念,陆续收集到面试中python ...

  6. Java面试必问之Hashmap底层实现原理(JDK1.7)

    1. 前言 Hashmap可以说是Java面试必问的,一般的面试题会问: Hashmap有哪些特性? Hashmap底层实现原理(get\put\resize) Hashmap怎么解决hash冲突? ...

  7. 五分钟学Java:如何学习Java面试必考的JVM虚拟机

    原创声明 本文首发于微信公众号[程序员黄小斜] 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 为什么要学习JVM虚拟机 最近的你有没有参加Java面试呢?你有没有发现,Java ...

  8. linux驱动工程面试必问知识点

    linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...

  9. 互联网公司面试必问的Redis题目

    Redis是一个非常火的非关系型数据库,火到什么程度呢?只要是一个互联网公司都会使用到.Redis相关的问题可以说是面试必问的,下面我从个人当面试官的经验,总结几个必须要掌握的知识点. 介绍:Redi ...

随机推荐

  1. 区块链共识机制之工作量证明(POW)

    像比特币.以太坊.NXT.Bitshares等这些区块链系统,其本质上是一种加密经济组织,它建立在点对点网络上,是去中心化.无管辖的,由密码学.经济学和社会共识来共同维护.这些加密网络因各种原因有着多 ...

  2. SpringBoot Application深入学习

    本节主要介绍SpringBoot Application类相关源码的深入学习. 主要包括: SpringBoot应用自定义启动配置 SpringBoot应用生命周期,以及在生命周期各个阶段自定义配置. ...

  3. Linux菜鸟——搭建虚拟机环境

    最近在学习Linux搭建服务器,但本人对于Linux一无所知,所以花了两天时间把安装,命令,控制,搭建环境等一系列操作都囫囵吞枣了一遍,但又怕自己记不住太多,所以记录下以前搭建的所有步骤,希望能提醒自 ...

  4. python_day03

    今日所学内容 1.函数部分: #函数的三种定义方式#1.无参函数:不需要外部传入的参数#2.有参函数:需要接受外部传入的参数#3.空函数:def func(): pass#pass代表说明都不用做# ...

  5. uniapp打包Android APP

    1.uniAPP 将项目打包成,打包成功后格式如下 2.下载相关工具 Android studio(打包成app的工具) 和Hbuilder官方SDK,安装解压响应工具 3. 用 Android st ...

  6. Windows使用Java执行cmd代码

    话不多说,直入正题 今天给大家分享下,怎么在Windows上使用Java执行Cmd代码! 首先默认大家都熟悉cmd代码,以及cmd的命令行操作. 直接在main方法中写这一行(需要抛出异常),可以直接 ...

  7. 2019-9-26:渗透测试,基础学习,nmap扫描kali虚拟机服务

    初识Nmap 1, 首先确定kali的ip地址,输入命令ifconfig 2, 开启所需要扫描的服务, 开启ssh:service ssh start, 确认ssh服务是否开启service ssh ...

  8. 【集训Day1 测试】【USACO】照相

    照相(fairphoto) [题目描述] 有N 头奶牛站在一条数轴上,第 i 头奶牛的位置是 Pi,奶牛不会重叠站在同一个位置, 第i 头奶牛的颜色是 Ci,其中 Ci 要么是字符'G'要么是字符'H ...

  9. 探索 Reflect.apply 与 Function.prototype.apply 的区别

    探索 Reflect.apply 与 Function.prototype.apply 的区别 众所周知, ES6 新增了一个全局.内建.不可构造的 Reflect 对象,并提供了其下一系列可被拦截的 ...

  10. django ListView

    context_object_name = 'posts'. The template default name is ListView 'object_list' from .models impo ...