让建站和SEO变得简单

让不懂建站的用户快速建站,让会建站的提高建站效率!

  • 口试必问的 JVM 运行时数据区,你懂了吗?

    发布日期:2022-03-13 19:45    点击次数:137
    绪言

    Java 虚构机的运行时数据区往往在口试中被拿来发问,好多倡导在市面上有多样种种的说法,搞的不少同学应该是懵逼的。

    当咱们堕入不廓清哪个说法是正确的情况时,最佳的参考即是源码和步骤。

    在口试中,当口试官反问你:为什么某某是这样?的时辰,若是你复兴:因为步骤是这样写的、因为源码是这样写的。

    这个复兴黑白常有劝服力的。

    因此,本文在描绘一些有争议的问题上,优先以《Java 虚构机步骤》的说法为准。

    正文 1、运行时数据区(Run-Time Data Areas)

    Java 虚构机界说了多少种在能力践诺时刻会使用到的运行时数据区域。

    其中一些数据区域在 Java 虚构机启动时被创建,跟着虚构机退出而糟跶。也即是线程间分享的区域:堆、样式区、运行往往量池。

    另外一些数据区域是按线程分别的,这些数据区域在线程创建时创建,在线程退出时糟跶。也即是线程间圮绝的区域:能力计数器、Java虚构机栈、腹地样式栈。

    1)能力计数器(Program Counter Register)

    Java 虚构机不错撑持多个线程同期践诺,每个线程都有我方的能力计数器。在职何时刻,每个线程都只会践诺一个样式的代码,这个样式称为该线程确现时列法(current method)。

    若是线程正在践诺的是 Java 样式(不是 native 的),则能力计数器记载的是正在践诺的 Java 虚构机字节码教唆的地址。若是正在践诺的是腹地(native)样式,那么计数器的值是空的(undefined)。

    2)Java虚构机栈(Java Virtual Machine Stacks)

    每个 Java 虚构机线程都有我方独到的 Java 虚构机栈,它与线程同期创建,用于存储栈帧。

    Java 虚构机栈描绘的是 Java 样式践诺的内存模子:每个样式在践诺的同期都会创建一个栈帧用于存储局部变量表、操作数栈、动态连气儿、样式出口等信息。

    每一个样式从调用直至践诺完成的经由,就对应着一个栈帧在虚构机栈中入栈到出栈的经由。

    3)腹地样式栈(Native Method Stacks)

    腹地样式栈与 Java 虚构机栈所发扬的作用黑白常相似的,它们之间的区别不外是 Java 虚构机栈为虚构机践诺 Java样式(也即是字节码)就业,而腹地样式栈则为虚构机使用到的腹地(Native)样式就业。

    4)堆(Heap)

    堆是被各个线程分享的运行时内存区域,亦然供总计类实例和数组对象分派内存的区域。

    堆在虚构机启动时创建,堆存储的对象不会被涌现开释,而是由垃圾汇注器进行挽回料理和回收。

    5)样式区(Method Area)

    样式区是被各个线程分享的运行时内存区域。样式区访佛于传统讲话的编译代码的存储区。它存储了每一个类的结构信息,举例:运行往往量池、字段和样式数据,构造函数和普通样式的字节码内容,还包括一些用于类、实例、接口运升沉用到的阑珊样式。

    6)运行往往量池(Run-Time Constant Pool)

    运行往往量池是 class 文献中每一个类或接口的常量池表(constant_pool table)的运行时暗示面目。

    它包含了多少种常量,从编译时已知的数值字面量到必须在运行时默契后才能赢得的样式和字段援用。运行往往量池的功能访佛于传统编程讲话的绚丽表(symbol table),不外它包含的数据鸿沟比浅近真理上的绚丽表要更为无为。

    2、Java 中有哪几种常量池?

    当今咱们往往提到的常量池主要有三种:class 文献常量池、运行往往量池、字符串常量池。

    3、class 文献常量池

    class 文献常量池(class constant pool)属于 class 文献的其中一项,class 类文献包含:魔数、类的版块、常量池、探询标志、字段表聚首、方发表等信息。

    常量池用于存放编译时刻生成的多样字面量(Literal)和绚丽援用(Symbolic References)。

    字面量相比接近于Java讲话层面的常量倡导,如文本字符串、声明为 final 的常量值等。

    绚丽援用则属于编译旨趣方面的倡导。绚丽援用是一组绚丽来描绘所援用的想法,绚丽不错是任何面目的字面量,只消使用时能无歧义地定位到想法即可(它与凯旋援用区分,凯旋援用一般是指向样式区的腹地指针,相对偏移量或是一个能蜿蜒定位到想法的句柄)。绚丽援用主要包括底下几类常量:

    被模块导出或绽放的包(Package) 类和接口的全适度名(Fully Qualified Name) 字段的称呼和描绘符(Descriptor)

    常量池中每一项常量都是一个表,约束JDK 13,常量表均分别有17种不同类型的常量。17种常量类型所代表的具体含义如图所示。

    对于 class 文献常量池的更多内容不错阅读周志明的《深化会通Java虚构机》6.3.2 章节。

    4、运行往往量池

    class 文献常量池是在类被编译成 class 文献时生成的。而当类被加载到内存中后,JVM 就会将 class 文献常量池中的内容存放到运行往往量池中。

    Java 虚构机步骤中对运行往往量池的界说如下:

    A run-time constant pool is a per-class or per-interface run-time representation of the constant_pool table in a class file.

    运行往往量池是 class 文献中每一个类或接口的常量池表(constant_pool table)的运行时暗示面目。

    因此,字据步骤界说,不错说运行往往量池是 class 文献常量池的运行时暗示,每个类在运行时都有我方的一个孤独的运行往往量池。

    5、字符串常量池

    节略来说,HotSpot VM 里的字符串常量池(StringTable)是个哈希表,全局惟有一份,被总计的类分享。

    StringTable 具体存储的是 String 对象的援用,而不是 String 对象实例自身。String 对象实例在 JDK 6 及之前是在长期代里,从JDK 7 首先放在堆里。

    字据 Java 虚构机步骤的界说,堆是存储 Java 对象的场地,其他场地是不会有 Java 对象实体的,若是有的话,字据步骤界说,这些场地也要算堆的一部分。

    6、字符串常量池是否属于样式区?

    我合计是不属于的。

    在读本文之前,我折服好多同学会有如下视力:因为运行往往量池属于样式区,是以好多同学合计字符串常量池也应该属于样式区。

    然则折服看了上头的内容后,会首先强劲到,运行往往量池和字符串常量池其实是不同的两个东西,固然它们在字符串默契时会干系联。

    Java 虚构机步骤中对样式区的界说如下:

    The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization

    在 Java 虚构机中,样式区是被各个线程分享的运行时内存区域。样式区访佛于传统讲话的编译代码的存储区,玩忽访佛于操作系统程度中的文本段。它存储了每一个类的结构信息,举例:运行往往量池、字段和样式数据,构造函数和普通样式的字节码内容,还包括一些用于类、实例、接口运升沉用到的阑珊样式。

    这边的枢纽在于 “它存储了每一个类的结构信息”,而字符串常量池并不属于某个类,字符串常量是全局分享的,因此,字据步骤界说,咱们不错说字符串常量池不属于样式区。

    那字符串常量池(StringTable)究竟存在那儿了?

    StringTable 本色是存储在 native memory(腹地内存)里,不是在长期代里,不是在样式区里,固然,更不是在堆里。

    7、运行往往量池和字符串常量池的关联?

    上头说了,运行往往量池和字符串常量池在字符串默契时会干系联,具体如下。

    类的运行往往量池中有 CONSTANT_String_info(见题3表格)类型的常量,CONSTANT_String_info 类型的常量的默契(resolve)经由如下:

    当先到字符串常量池(StringTable)中查找是否还是有了该字符串的援用,若是有,则凯旋复返字符串常量池的援用;若是莫得,则在堆中创建 String 对象,并在字符串常量池驻留其援用,然后复返该援用。

    也就说,运行往往量池里的 CONSTANT_String_info 类型的常量,经过默契(resolve)之后,相同存的是字符串的援用,况且和 StringTable 驻留的援用的是一致的。

    8、String#intern 样式

    在 JDK 7 及之后的版块中,该样式的作用如下:若是字符串常量池中还是有这个字符串,则凯旋复返常量池中的援用;若是莫得,则将这个字符串的援用保存一份到字符串常量池,然后复返这个援用。

    底下的例子不错进行节略的考据:

    public static void main(String args[]) {      // 创建2个对象,str持有的是new创建的对象援用     // 1)驻留(intern)在字符串常量池中的对象     // 2)new创建的对象     String str = new String("joonwhee");     // 字符串常量池中还是有了,复返字符串常量池中的援用     String str2 = "joonwhee";     // false,str为new创建的对象援用,str2为字符创常量池中的援用     System.out.println(str == str2);     // str修改为字符串常量池的援用,是以底下为true     str = str.intern();     // true     System.out.println(str == str2); } 
    9、长期代(PermGen)

    长期代在 Java 8 被移除。字据官方提案的描绘,移除的主要动机是:要将 JRockit 和 Hotspot 进行会通,而 JRockit 并莫得长期代。

    而据咱们所了解的,还有另外一个进攻原因是长期代自己也存在较多的问题,往往出现OOM,还出过不少bug。

    字据官方提案的描绘,长期代主要存储了三种数据:

    1)Class metadata(类元数据),也即是样式区中包含的数据,除了编译生成的字节码被放在 native memory(腹地内存)。

    2)interned Strings,也即是字符串常量池中驻留援用的字符串对象,字符串常量池只驻留援用,而施行对象是在长期代中。

    3)class static variables,类静态变量。

    移除长期代后,interned Strings 和 class static variables 被转移了堆中,Class metadata 被转移到了其后的元空间。

    10、长期代和样式区的关系?

    样式区是 Java 虚构机步骤中界说的一种逻辑倡导,而长期代是对样式区的终了。然则长期代并不等同于样式区,样式区也不等同于长期代。

    长期代中的 interned Strings 并不属于样式区,按步骤:堆是存储 Java 对象的场地 ,这部分应该属于堆,因此长期代并不是只用于终了样式区。

    样式区中 JIT 编译生成的代码并不是存放在长期代,而是在 native memory 中,因此不错说样式区也并不仅仅由长期代来终了。

    11、元空间(metaspace)

    元空间在 Java 8 移除长期代后被引入,用来代替长期代,本质和长期代访佛,都是对样式区的终了。不外元空间与长期代之间最大的区别在于:元空间并不在虚构机中,而是使用腹地内存(native memory)。

    元空间主要用于存储 Class metadata(类元数据),字据其定名其实也看得出来。

    不错通过 -XX:MaxMetaspaceSize 参数来限制元空间的大小,若是莫得征战该参数,则元空间默许限制为机器内存。

    12、为什么引入元空间?

    在 Java 8 之前,Java 虚构机使用长期代来存放类元信息,通过-XX:PermSize、-XX:MaxPermSize 来约束这块内存的大小,跟着动态类加载的情况越来越多,这块内存变得不太可控,到底征战多大相宜是每个征战者要磋商的问题。

    若是征战小了,容易出现内存溢出;若是征战大了,又有点肆虐,尽管不会实质分派这样大的物理内存。

    而元空间不错较好的科罚内存征战多大的问题:当咱们莫得指定 -XX:MaxMetaspaceSize 时,元空间不错动态的治愈使用的内存大小,以容纳赓续加多的类。

    13、元空间能透彻科罚内存溢出(Out Of Memory)问题吗?

    很缺憾,谜底是不成的。

    元空间无法透彻科罚内存溢出的问题,只可说是有所缓解。当内存使用罢了后,元空间一样会出现内存溢出的情况,最典型的场景即是出现了内存走漏时。

    本文转载自微信公众号「能力员囧辉」,不错通过以下二维码热心。转载本文请筹商能力员囧辉公众号。

     



上一篇:没有了    下一篇:华尔街见闻早餐FM-Radio|2022年1月7日