一个Java类在运行时候,变量是怎么在JVM中分布的呢?
JVM学习第三篇思考:一个Java类在Jvm内存中是怎么存在的
又名:Java虚拟机的内存模型(JMM)是什么样的.
通过前面两篇文章的学习,我们知道了一个Java类的生命周期及类加载器。我们可以得到如下两幅图:
类生命周期:
父类委托机制:
思考:
我们编写的类中的变量、方法、对象这些都需要内存存放的。那么在运行时候这些数据在Java虚拟机内存中是怎么存放的呢?
本文目标:
凯哥(凯哥Java:kaigejava)希望通过本文学习,大家对Java虚拟机运行时数据区域有更深的了解
我们写的代码在JVM中是怎么存在的?
1:我们现在看看总体Java运行时数据模型:
2:我们来看看下面这段代码,执行的时候,在JVM中数据存放:
上面代码很简单,那么对应的变量、对象等在内存中都是怎么分配的呢?
2.1:方法区
注:在JDK1.8之后,方法区被元空间替换了。
方法区:用来存放的是类的信息、常量、静态变量等。该区域也是各个线程共享的内存区域。
根据Java虚拟机规范中的规定,当方法去无法满足内存分配的时候,会抛出:OutOfMemoryError异常的。
根据上面的 定义,我们可以知道比如我们JvmDemo.class信息、static string str=“jvmDemo”是在方法区存放的。
对应咱们代码,方法区存放的如下图:
2.2:堆区
堆区是JVM所管理的内存中的最大的一块区域。该区域是所有线程共享的一块内存区域。该区域空间在虚拟机启动的时候就被创建了(-Xms的设置。后面凯哥(凯哥Java:kaigejava)也会详细讲解的)。
此区域的目的是存放对象实例的。几乎所有的对象实例都是在这里分配的。Java虚拟机规范中是这么描述的:所有的对象的实例以及数组都要在堆上分配。
堆区是垃圾收集器管理的主要区域(后面凯哥(凯哥Java:kaigejava)也会详细讲解的).
堆区空间,在物理上可以不是连续的内存空间,只要在逻辑上是连续的即可。如果堆没有内存完成实例分配,并且堆也无法在扩展的时候,将会抛出异常:OutOfMemoryError。这个大家很熟悉吧。
根据上面定义的,我们可以知道,上面代码中Son son = new Son(); 这行代码创建的实例对象是存放在堆区的。
2.3:程序计数器
程序计数器的作用可以看做是当前线程所执行的字节码的行号指示器。字节码解释器在工作的时候,时候通过改变计数器的值来选择接下来要执行的字节码指令的。
同时我们都知道,当多线程的时候,Java虚拟机是通过线程轮流切换分配处理器执行时间的方式来实现的。在任何一个确定的时刻一个处理器只会执行一条线程中的指令。因此,为了解决多个线程在切换后,能够迅速恢复到切换前执行的位置,每个线程都需要有个独立的程序计数器,各个线程直接的计数器互不影响,独立存储的。一般称这类内存区域为:"线程私有"的内存。当线程正在执行的一个方法是Native的,这种情况下,计数器的值就是undefined了。这个区域也是Java虚拟机内存区域中唯一一个没有OOM的区域。
根据上面描述,我们可以知道,我们自己编写的*.java文件要想被执行,需要被编译成*.class的字节码文件。字节码文件对应各种字节码指令。比如我们上面JvmDemo的字节码文件:
从上面截图,我们可以看到,行号是0,3,4,7,8这样的。程序计数器就是记录这些行号的
我们也可以使用idea的插件,来查看我们JvmDemo的相关信息:
2.4:虚拟机栈
Java虚拟机栈,也是线程私有的。其生命周期与线程相同,当一个线程运行结束后,对应的虚拟机栈也结束。
虚拟机栈是Java方法执行的内存模型:即每个方法被执行的时候,都会被同时创建一个栈帧(Stack Frame),这个栈帧是用来存放方法局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直到其执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈和出栈的过程。
比如:我们上面代码执行的时候,执行main方法的时候,主线程就会把main方法压入到虚拟机栈中,当执行到add方法的时候,add方法就被压入到栈中了。当执行完add方法后,add方法就被从虚拟机栈中弹出,这个时候add对应的栈帧也销毁。
虚拟机栈帧如下图:
局部变量存放:各种基本数据类型、对象引用和返回类型
八大基本数据类型:boolean、byte、char、short、init、float、long、double;
对象引用:reference类型。这里是存放的是对象在对内存中的地址值。不等同于对象自身的。根据不同的虚拟机的实现,这个指向可能是指向了对象起始地址的引用指针,也有可能是指向了对象对象的句柄或其他对象与其他对象的位置;
返回类型:returnAddress类型。指向一条字节码指令地址。
扩展:long类型和double类型的数据会占用2个局部变量空间。其他6个数据类型占用1个。
局部变量表所消耗的内存空间在编译期间就完成了分配,当进入一个方法的时候,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的。在方法的运行期间,不会改变该区域空间大小的。
在咱们上面代码中,虚拟机栈存放的就是咱们main方法和add方法相关的
2.5:本地方法栈
本地方法栈的作用和虚拟机栈的作用相似。不同之处在于:虚拟机栈是为了虚拟机执行Java方法服务的。而本地方法栈则是为了虚拟机使用到Native方法服务的。此区域也是方法私有的。比如我们调用线程的run方法或者CAS的时候,调用的都是native方法。
总结:
通过本文学习,我们在自己脑海中应该有如下图的概念:
其中方法区、堆区是所有线程共享的;虚拟机栈、程序计数器、本地方法栈这三个是线程私有的,其生命周期同线程一致。
方法区:存放类型、常量、静态变量等
堆区:用来存放对象实例、数组
虚拟机栈:局部变量表、动态链接、操作栈等
本地方法栈:用来存放当线程调用native方法的时候使用的
程序计数器:用来记录当前线程执行的字节码行号的。
好了,本文凯哥(凯哥Java:kaigejava)就和大家唠唠在运行时候Java虚拟机的数据区域。在下篇文章中,咱们在详细唠唠堆区。
一个Java类在运行时候,变量是怎么在JVM中分布的呢?的更多相关文章
- 假如java类里的成员变量是自身的对象
假如java类里的成员变量是自身的对象,则新建该类对象时内存中怎么分配空间,我感觉似乎死循环了. 不过我想的肯定是错的,因为很多类的成员变量是自身对象,并且绝对无错,举个例子: Class A{ pr ...
- java类里的成员变量是自身的对象问题
今晚看单例模式饿汉时想到一个问题:假如java类里的成员变量是自身的对象,则新建该类对象时内存中怎么分配空间,我感觉似乎死循环了.于是上网搜索了下,哈哈,果然有人早就思考过这个问题了,站在巨人的肩膀上 ...
- 如何唯一确定一个 Java 类?
今天偶然想起之前和朋友讨论过的一个问题:如何唯一确定一个 Java 类?我相信大多数朋友遇到这个问题的回答都是:类的全路径呗.但事实上,唯一确定一个 Java 类,单单靠类路径是不够的,还要多加上一个 ...
- 第一次尝试学习java 安装jdk 与配置环境变量 写第一个java程序 并运行
第一次学习java,今天知道了java之父叫 詹姆斯.高司令 其它的记不住太多,首先我们先来安装jdk 百度搜索jdk12 (现在的jdk为12版本)安装稳定版 找到javaSE12X.. 下 ...
- 测试 Java 类的非公有成员变量和方法
引言 对于软件开发人员来说,单元测试是一项必不可少的工作.它既可以验证程序的有效性,又可以在程序出现 BUG 的时候,帮助开发人员快速的定位问题所在.但是,在写单元测试的过程中,开发人员经常要访问类的 ...
- JAVA类与对象---实例变量与类变量的区别,实例方法和类方法的区别
实例变量 实例变量声明在一个类中,但在方法.构造方法和语句块之外: 当一个对象被实例化之后,每个实例变量的值就跟着确定: 实例变量在对象创建的时候创建,在对象被销毁的时候销毁: 实例变量的值应该至少被 ...
- 1--我们写了一个java类,那么生成一个对象占用多大的内存?
public class Student { private long id; private long userId; private byte state; private long create ...
- mac os intellij如何快路查看一个java类的所有方法,结构
如果是自己写的java类,点击点击导航的project-setting-show members 如果是系统库的,点击structure 再点一下lib中的类,或者快捷键 command+F12
- 【Java.Regex】使用正则表达式查找一个Java类中的成员函数
代码: import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; imp ...
- 使用log4j使某些java类的日志信息输出到指定日志文件中
Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI 组件.甚至是套接口服务器.NT 的事件记录器.UNIX Syslog ...
随机推荐
- mapreduce的shuffle机制
1.1 概述: mapreduce中,map阶段处理的数据如何传递给reduce阶段,是mapreduce框架中最关键的一个流程,这个流程就叫shuffle:(从map的输出到reduce的输入) s ...
- windows10 iis 环境下部署 asp.net core 应用程序的步骤
1.运行powershell,在运行窗口中输入:powershell,点回车,如下图: 2.安装choco,在打开的powershell窗口中输入:Set-ExecutionPolicy Bypass ...
- python3 pip3 安装 xmlrpc 失败
python2 使用的是xmlrpclib库,到了 python3, 就直接使用 xmlrpc.client 和 xmlrpc.server了. 接下来,我使用 pip3 install xmlrpc ...
- Maven的依赖详解和打包方式
设置maven maven下载与安装教程: https://blog.csdn.net/YOL888666/article/details/122008374 1. 在File->setting ...
- vue3时间转换插件-Moment.js的使用
vue3时间转换插件-Moment.js的使用 一.组件官网moment.js时间转换插件http://momentjs.cn/Moment Timezone 时区处理类库http://momentj ...
- log4js 的安装设置和实例
1. 安装 yarn add log4js -D 2.设置 const log4js = require('log4js') 3.实例 var log = log4js.getLogger(); // ...
- oeasy教您玩转vim - 59 - # 编辑总结
[Github地址] (https://github.com/overmind1980/oeasyvim) [Gitee地址] (overmind1980/oeasyvim) [蓝桥实验楼 邀请码 ...
- 数据分析应该掌握的知识及SQL技能
一.概念及常识 1.数据分析必备的统计学知识 描述统计学 1.平均值.中位数.众数 2.方差.标准差 3.统计分布:正态分布.指数分布.二项分布.卡方分布 推论统计学 1.假设检验 2.置信区间 3. ...
- 靶机练习: hacksudo---Thor
靶机:hacksudo---Thor 准备工作 靶机地址: http://download.vulnhub.com/hacksudo/hacksudo---Thor.zip MD5 校验:d12168 ...
- 关于elementUI的select组件回显问题
最近接受了一个后台项目,需求是这样的,点击表单项,弹出的弹出层显示该表单项目的信息.但是回显的时候,关于弹出层中的级联显示有问题,如图: 回显结果为: 回显代码为: 弹框为: 我就不明白了,分明分公司 ...