• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于java:java虚拟机运行时数据区域

java 搞代码 3年前 (2022-02-19) 46次浏览 已收录 0个评论

1.虚拟机外部状况

虚拟机标准定义的运行时数据区域:

jdk1.8后理论的虚拟机运行时数据区域:

jdk1.8后的hotspot实现的虚拟机运行时数据区域和标准的几个不同点:

  • 将虚拟机栈和本地办法栈合二为一;
  • 元数据区取代办法区,并且不在虚拟机内存中,而是在本地内存中;
  • 运行时常量池由办法区移到了堆中;

2.虚拟机栈


虚拟机栈为线程公有的区域,由栈帧组成。每执行一个办法都会创立一个栈帧,用于存储局部变量表,操作数栈,动静链接和办法返回地址等信息。每一个办法从被调用到执行实现的过程就是一个栈帧入栈和出栈的过程。如果虚拟机栈的大小固定,那么当申请的栈深度超过虚拟机栈的深度的时候就会抛出StackOverflowError异样(常见与递归调用)。如果虚拟机栈能够有限扩大的时候,当扩大时无奈申请到足够的内存时会抛出OutOfMemoryError异样。

3.本地办法栈

本地办法栈和虚拟机栈非常相似,惟一的不同就是虚拟机栈存储的是java办法,而本地办法栈存储的是Native办法。jdk1.8后本地办法栈和虚拟机栈曾经合二为一。

4.程序计数器

线程公有的区域。记录以后线程执行的地址,因为在并发的状况下,每个线程都是片段执行的,因而须要一个区域记录以后线程执行到的地址,不便从新调用的时候可能疾速复原执行。

5.堆

堆是线程共享的区域。用来存储实例化对象。基本上所有实例化对象和数组都存储在堆上,也是垃圾回收机制作用的次要区域。

6.办法区

用来存储已被虚拟机加载的类信息,常量,动态变量等数据。办法区又称为“永恒代”因为对于办法区的垃圾回收条件十分刻薄,往往不会进行回收。在jdk1.8中去掉了办法区的概念,将其中的运行时常量池移到了堆中,其余局部改为Metaspace(元数据区)存储在间接内存中。

7.运行时常量池

用于寄存字面量,符号援用和间接援用。首先看以下的代码:

<code class="java">public class Main{
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
      <b style="color:transparent">来源gao@dai!ma.com搞$代^码网</b>  System.out.println(str1 == str2); // true
        System.out.println(str1 == str3); // false
        System.out.println(str2 == str3); // false
    }
}

如果以下面代码中的str1和str2的创立形式,虚构机会先查看运行时常量池中是否又“hello”对象,显然在str1创立的时候是不存在“hello”对象的,因而会在运行时常量池创立一个“hello”对象,当str2赋值的时候先查看常量池中是否有,发现有,则不进行创立,而是间接使str2指向存在的str1,因而str1 == str2 是true的。
而str3应用new关键字创立,则会在堆中先创立一个str3对象,此时str3是指向堆中的这个对象的而不是指向常量池中。因而str3和str1,str2比拟都是false。而创立完对象之后再去查看常量池中是否有“hello”对象,有的话再使堆中的对象指向常量池。如果new创立的对象字符串值在运行时常量池中并没有,则不会再在常量池中对变量值进行保护。

<code class="java">public class Main {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "helloworld";
        String str3 = str1 + "world";
        String str4 = "hello" + "world";
        System.out.println(str2 == str3); // false
        System.out.println(str2 == str4); // true
        System.out.println(str3 == str4); // false
    }
}

这下面的例子,首先str1和str2显然是指向常量池的两个不同的对象。即当初常量池中有“hello”和“helloworld”两个对象。创立str3的时候因为蕴含了str1,虚拟机无奈判断str3是否是常量,因而与new办法相似,会在堆中创立一个“helloworld”,并在查看后发现常量池中也有一个“helloworld”,因而再有堆中的对象指向常量池,但记住此时的str3指向的仍然是堆中的对象而十分量池,因而str2==str3后果是false。而str4是以显式的常量进行创立的,因而在查看过后也是间接指向常量池中的“helloworld”,故str2==str4是true。str3==str4也是不言而喻了。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于java:java虚拟机运行时数据区域

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址