【JAVA进阶架构师指南】之二:JVM篇

前言

  谈到JAVA,就不得不提JVM—JAVA程序员绕不开的话题.也许有童鞋会说,我不懂JVM,然则我一样可以写出JAVA代码,我信赖说这种话的童鞋,往往是只有1-3年的低级开发人员,对JAVA明了还不深,不明了JVM的主要性,那接下来我们来说说,为什么要学习JVM?
  1.明了JVM,才气辅助我们写出更好,更结实的代码.举个例子,以下代码的执行效果会是什么呢?许多童鞋一定会说:嗯?当我傻吗?两个不都是true吗?这有啥好说的,真的是这样吗?感兴趣的童鞋可以自己下来试一试,至于为什么是这样的效果,在下文会注释清晰.
【JAVA进阶架构师指南】之二:JVM篇
  2.明了JVM,可以辅助我们提升JAVA程序的性能,清扫问题.
  3.也是最主要的一点,面试必问!

虚拟机的种类

  我们知道,现在使用局限最广的虚拟机是sun公司的HotSpot VM,在这之前,sun公司公布的第一款虚拟机是Sun Classic/Exact VM,这是世界上第一款商用虚拟机.另外其他公司也有自己的虚拟机,好比IBM J9 VM,Google Android Dalvik VM,Apache Harmony,Microsoft VM守候,然则使用局限最广的照样HotSpot.

JVM内存划分

  引用一张图来说明:
【JAVA进阶架构师指南】之二:JVM篇

  可以看到,JVM主要由方式区/堆区/虚拟机栈/内陆方式栈/程序计数器五个部门组成,从线程的角度来看,分为线程公有的部门(方发区/java堆)和线程私有的部门(虚拟机栈/内陆方式栈/程序计数器).

方式区

  存放已经被虚拟机加载的[类信息/常量/静态变量/即时编译后的代码]等,有些文章也称方式区为永远代,主要发生的异常是内存溢出:OutOfMemoryError.另外在JDK1.6版本中,常量池(这里特指运行时常量池,我们一样平常说的常量池也都是指的运行时常量池)是存放于方式区中的(因此方式区可能会经常内存溢出),JDK1.7的时刻常量池移到了JAVA堆(Heap)中,在JDK1.8的时刻,已经没有方式区了,取而代之的是一块叫元数据(metaSpace)的空间.

java堆

  java堆主要存放的是工具实例以及数组等信息,主要发生的异常仍然是内存溢出:OutOfMemoryError.而且java堆区是GC重点关注的区域.另外,我们常说,险些所有的工具分配内存都是在java堆中举行,而不是说所有工具100%都在java堆中分配内存,是由于有两种例外情形不会在java堆中分配内存,第一种是TLAB(线程本机分配缓存),另一种是栈上分配,既然想成为一名架构师,童鞋们应该要弄明了什么是TLAB和栈上分配,施展你们的能力,恣意Google吧.

Excel表格转Json数据结构

虚拟机栈

  java方式执行的内存模子,每个方式在执行的时刻会封装成一个栈帧,存放[局部变量表/操作数栈/动态链表/方式出口]等信息,方式的执行对应栈帧入栈和出栈的历程.栈的深度是有巨细的,默认情形下栈的内存为1M,因此虚拟机栈除了发生内存溢出异常,另有可能发生StackOverFlowError异常.

本机方式栈

  和虚拟机栈作用类似,区别在于内陆方式栈保留的是native方式的信息.

程序计数器

  当前线程执行的字节码行号指示器,是JVM中唯一一块没有内存溢出异常的区域.

常量池

  接下来我们再倒回来看看,文章开头的代码,执行效果会是什么:
【JAVA进阶架构师指南】之二:JVM篇
  127返回的是true,128返回的确是false.为什么?
  首先我们知道,在java语言中 == 对照的是两个工具的内存地址,只有equals方式才是对照两个工具是否相等,执行效果告诉我们,值都为127的Integer a和b内存地址是相同的,他们是同一个工具,而值为128的Integer c和d的内存地址差别,他们是差别的两个工具,那为什么127就是相同的工具,128就是差别的工具呢?还记得上文中,我们说方式区中有一块区域叫运行时常量池,存放的是种种常量,java语言对byte/short/char/int/string设置了常量池,好比我们查看Integer的源码:
【JAVA进阶架构师指南】之二:JVM篇
  可以发现,Integer的常量池局限是-128~127,在该局限内的Integer工具都市复用常量池中的值,因此a和b是相同工具,而跨越该局限,会重新new一个新的工具,因此c和d都是重新new出来的,地址固然差别,因此是false.另外String类型的常量池和前面四种类型不一样,String类型的常量池是通过final来实现的.而float/double没有常量池的观点,由于float和double自己都是科学手艺法示意近似数,无法正确盘算,存在精度丢失的情形,因此没法为float和double建立常量池.

  本文我们了解了JVM的内存区域,下一篇文章,让我们来学习类加载机制,敬请期待!

  若是以为博主写的不错,迎接关注博主微信民众号,博主会不定期分享手艺干货!
  【JAVA进阶架构师指南】之二:JVM篇

本文由博客一文多发平台 OpenWrite 公布!

原创文章,作者:28x0新闻网,如若转载,请注明出处:https://www.28x0.com/archives/2036.html