jvm内存模型 知乎_简述对JVM的理解「建议收藏」

jvm内存模型 知乎_简述对JVM的理解「建议收藏」JVM屏蔽了与操作系统平台相关的信息,使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“一次编译,到处运行的”原因

一、JVM是什么?

JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关的信息,使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“一次编译,到处运行的”原因。

二、JVM内存模型图

在这里插入图片描述

三、JVM运行数据区详解
  1. JVM运行数据区分为虚拟机栈、本地方法栈、程序计数器、堆区、元空间(方法区)五部分。其中虚拟机栈、本地方法栈和程序计数器属于线程私有,而堆、元空间属于线程共享。
    在这里插入图片描述
  2. 虚拟机栈中存储方法、方法中的局部变量、以及运行时数据,本地方法栈和虚拟机栈类似,只不过本地方法中栈存储的是本地方法的一些数据信息,程序计数器用来表示程序代码的执行位置,每一线程工作时,都会开辟自己的虚拟机栈、本地方法栈、和程序计数器。
  3. 堆区,存储对象信息,以及数组,是所有线程共享区域、
  4. 元空间存储类加载的相关信息,以及静态变量、常量、运行时常量池等。

下面,以代码演示各个位置存储的信息:

		//1.首先类加载器将类加载到原空间
	public class Application { 
   
    	//main线程--> main的线程栈,也就是虚拟机栈
    	//2.执行main 方法,将main方法压入栈
    	public static void main(String[] args) throws Exception { 
   
        //3.load方法压入虚拟机栈
        load();
        System.in.read();        //保证程序不要退出
     }
        public static void load() { 
   
        //4.在堆区创建Config对象,同时在栈区存储对象的引用地址,指向堆区
            Config config = new Config();
        //5.将loadData()方法压入栈
            config.loadData() ;
        }
    }
public class Config { 
   
    //1.静态变量存储在元空间
    public static Manager mdnagerl = new Manager();
    //2.实例变量/对象变量 和类对象一起存储在堆区
    private int a;
	//3.loadData()存储在方法区
    public String loadData() { 
   
        return "abc";
    }
}

在这里插入图片描述

四、JVM运行数据区各部分特点及作用

  1.   堆用来存放对象和数组,只要是堆中的对象,就可以被所有线程共享(静态变量、静态常量、字符串存储在堆中的老年代里)。Java7 版本中将永久代的静态变量和运行时常量池转移到堆中存放的。
      
      堆是 JVM 上最大的内存区域。垃圾回收操作的对象就是堆。
      
      堆空间一般是程序启动时就申请了,一般设置成可伸缩的。 随着对象的频繁创建,堆空间占用的越来越多,就需要不定期的对不再使用的对象进行回收,这就是GC。
      
       对于基本数据类型对象(如byte、short、int、long、float、double、char),在方法体内声明时,会直接分配在栈中,其它情况都会分配在堆中。
      
      对于普通对象来说,JVM 会首先在堆上创建对象,然后在其他地方使用它的引用。比如,把这个引用保存在虚拟机栈的局部变量表中。但是在开启了逃逸分析时,如果发现某个对象只会在方法内部使用,则可能会将该对象经过标量替换后也存在栈中。
      
    堆的几个重要参数:
      -Xms:堆的最小值(初始值,默认单位是:字节,要求是1024的整数倍);
      -Xmx:堆的最大值;
      -Xmn:新生代的大小;
      -XX:NewSize;新生代最小值(初始值);
      -XX:MaxNewSize:新生代最大值;

2.虚拟机栈
   Java虚拟机栈是当前线程在执行方法时存储所需的数据、指令、返回地址的一种栈结构(先进后出)。它的生命周期与线程保持一致。提一句:静态变量不入栈。
  
   每调用一个方法就会在栈里加入一个栈帧。调用的方法执行完了,对应的栈帧就会出栈。栈帧里分为4个区域,这4个区域就包含了执行Java方法时的全部内容。这个4个区域分别是:局部变量表、操作数栈、动态连接、方法出口。
在这里插入图片描述
虚拟机栈默认1M。 如果我们不断的往虚拟机栈中入栈帧,但是就是不出栈的话,那么这个虚拟机栈就会溢出。

3.程序计数器
   由于现在都是多线程运行,而一个CPU在同一时刻只能运行一个线程,多个线程只能交替运行。程序计数器的作用就是记录当前线程下一条要运行的指令,这样保证了线程在切换回来时能回到正确的位置继续开始执行
   程序计算器是唯一不会发生内存溢出的地方。如果正在执行的是Native 方法,由于不是JVM执行,则这个计数器值为空(Undefined)

4.方法区(元空间)
   方法区也是一个线程共享的内存区。
  
   方法区存储的内容有:类型信息(比如类全称、父类全称)、域信息(域名称、域修饰符private等)、方法信息(方法名称、方法修饰符、返回类型等)、字面量(字面量包括文本字符串、八种基本类型的值 、被声明为final的常量等)。
  
  假如两个线程都试图访问方法区中的同一个类信息,而这个类还没有加载进 JVM,那么此时就只允许一个线程去加载它,另一个线程必须等待。
  
  方法区是 JVM 对内存的“逻辑划分”,在 JDK1.7 及之前将方法区称为“永久代”,是因为在 HotSpot 虚拟机中,设计人员使用了永久代来实现了 JVM 规范的方法区。在 JDK1.8 及以后使用了元空间来实现方法区。
  
  Java8 使用元空间替代永久代,是为了融合 HotSpot JVM 与 JRockit VM ,因为 JRockit 没有永久代。
  
  元空间大小参数设置:
  jdk1.7 及以前:-XX:PermSize;-XX:MaxPermSize;
  jdk1.8 以后:-XX:MetaspaceSize; -XX:MaxMetaspaceSize ;如果不设置参数,则只受本机总内存的限制

今天的文章jvm内存模型 知乎_简述对JVM的理解「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/70089.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注