JVM运行原理及Stack和Heap的实现过程

2023-11-07

Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’(.class文件,也就是0,1二进制程序),然后在OS之上的Java解释器中解释执行,而JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。

注:本网站为码农们提供的大量编程教程: java教程java实例php教程mysql教程css教程html教程javascript教程oracle教程等等,如有兴趣,大家可以学习。

一、JVM原理

1、JVM简介:

JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。

java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。

2.Java语言运行的过程

Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’(.class文件,也就是0,1二进制程序),然后在OS之上的Java解释器中解释执行。

JVM运行原理及Stack和Heap的实现过程

简单点的话也和下面的原理差不多

JVM运行原理及Stack和Heap的实现过程

 

3、JVM执行程序的过程 :

I.加载。class文件

II.管理并分配内存

III.执行垃圾收集

JRE(java运行时环境)由JVM构造的java程序的运行环境

JVM运行原理及Stack和Heap的实现过程

 

二、JVM中的Stack和Heap

在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题。

1、简介

Stack(栈)是JVM的内存指令区。Stack管理很简单,push一定长度字节的数据或者指令,Stack指针压栈相应的字节位移;pop一定字节长度数据或者指令,Stack指针弹栈。Stack的速度很

快,管理很简单,并且每次操作的数据或者指令字节长度是已知的。所以Java 基本数据类型,Java 指令代码,常量都保存在Stack中。

Heap(堆)是JVM的内存数据区。Heap 的管理很复杂,每次分配不定长的内存空间,专门用来保存对象的实例。在Heap 中分配一定的内存来保存对象实例,实际上也只是保存对象实例的

属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中),在Heap 中分配一定的内存保存对象实例和对象的序列化比较类似。而对象实例在Heap

中分配好以后,需要在Stack中保存一个4字节的Heap 内存地址,用来定位该对象实例在Heap 中的位置,便于找到该对象实例。

下图为JVM的体系结构

JVM运行原理及Stack和Heap的实现过程

2、什么是数据、什么是指令,对象的方法和对象的属性又是什么?

1)方法本身是指令的操作码部分,保存在Stack中;

2)方法内部变量作为指令的操作数部分,跟在指令的操作码之后,保存在Stack中(实际上是简单类型保存在Stack中,对象类型在Stack中保存地址,在Heap 中保存值);上述的指令操作码和指令操作数构成了完整的Java 指令。

3)对象实例包括其属性值作为数据,保存在数据区Heap 中。

非静态的对象属性作为对象实例的一部分保存在Heap 中,而对象实例必须通过Stack中保存的地址指针才能访问到。因此能否访问到对象实例以及它的非静态属性值完全取决于能否获得对象实例在Stack中的地址指针。

3、非静态方法和静态方法的区别:

非静态方法有一个和静态方法很重大的不同:非静态方法有一个隐含的传入参数,该参数是JVM给它的,和我们怎么写代码无关,这个隐含的参数就是对象实例在Stack中的地址指针。因此非静态方法(在Stack中的指令代码)总是可以找到自己的专用数据(在Heap 中的对象属性值)。当然非静态方法也必须获得该隐含参数,因此非静态方法在调用前,必须先new一个对象实例,获得Stack中的地址指针,否则JVM将无法将隐含参数传给非静态方法。

静态方法无此隐含参数,因此也不需要new对象,只要class文件被ClassLoader load进入JVM的Stack,该静态方法即可被调用。当然此时静态方法是存取不到Heap 中的对象属性的。

小结::当一个class文件被ClassLoader load进入JVM后,方法指令保存在Stack中,此时Heap 区没有数据。然后程序技术器开始执行指令,如果是静态方法,直接依次执行指令代码,当然此时指令代码是不能访问Heap 数据区的;如果是非静态方法,由于隐含参数没有值,会报错。因此在非静态方法执行前,要先new对象,在Heap 中分配数据,并把Stack中的地址指针交给非静态方法,这样程序技术器依次执行指令,而指令代码此时能够访问到Heap 数据区了。

静态属性和动态属性:

前面提到对象实例以及动态属性都是保存在Heap 中的,而Heap 必须通过Stack中的地址指针才能够被指令(类的方法)访问到。

因此可以推断出:静态属性是保存在Stack中的,而不同于动态属性保存在Heap 中。正因为都是在Stack中,而Stack中指令和数据都是定长的,因此很容易算出偏移量,也因此不管什么指令(类的方法),都可以访问到类的静态属性。也正因为静态属性被保存在Stack中,所以具有了全局属性。

在JVM中,静态属性保存在Stack指令内存区,动态属性保存在Heap数据内存区。

总结:

1)、栈是运行时的单位,而堆是存储的单位。

2)、栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储的问题,即数据怎么放、放在哪儿。

4、为什么要把堆和栈区分出来呢?

第一,从软件设计的角度看,栈代表了处理逻辑,而堆代表了数据。这样分开,使得处理逻辑更为清晰。分而治之的思想。这种隔离、模块化的思想在软件设计的方方面面都有体现。

第二,堆与栈的分离,使得堆中的内容可以被多个栈共享(也可以理解为多个线程访问同一个对象)。这种共享的收益是很多的。一方面这种共享提供了一种有效的数据交互方式(如:共享内存),另一方面,堆中的共享常量和缓存可以被所有栈访问,节省了空间。

第三,栈因为运行时的需要,比如保存系统运行的上下文,需要进行地址段的划分。由于栈只能向上增长,因此就会限制住栈存储内容的能力。而堆不同,堆中的对象是可以根据需要动态增长的,因此栈和堆的拆分,使得动态增长成为可能,相应栈中只需记录堆中的一个地址即可。

第四,面向对象就是堆和栈的完美结合。其实,面向对象方式的程序与以前结构化的程序在执行上没有任何区别。但是,面向对象的引入,使得对待问题的思考方式发生了改变,而更接近于自然方式的思考。当我们把对象拆开,你会发现,对象的属性其实就是数据,存放在堆中;而对象的行为(方法),就是运行逻辑,放在栈中。我们在编写对象的时候,其实即编写了数据结构,也编写的处理数据的逻辑。

程序要运行总是有一个起点的。同C语言一样,java中的Main就是那个起点。无论什么java程序,找到main就找到了程序执行的入口:)

5、堆中存什么?栈中存什么?

1)、堆中存的是对象。栈中存的是基本数据类型和堆中对象的引用。一个对象的大小是不可估计的,或者说是可以动态变化的,但是在栈中,一个对象只对应了一个4btye的引用。

2)、为什么不把基本类型放堆中呢?因为其占用的空间一般是1~8个字节——需要空间比较少,而且因为是基本类型,所以不会出现动态增长的情况——长度固定,因此栈中存储就够了,如果把他存在堆中是没有什么意义的(还会浪费空间,后面说明)。可以这么说,基本类型和对象的引用都是存放在栈中,而且都是几个字节的一个数,因此在程序运行时,他们的处理方式是统一的。但是基本类型、对象引用和对象本身就有所区别了,因为一个是栈中的数据一个是堆中的数据。最常见的一个问题就是,Java中参数传递时的问题。

3)、Java中的参数传递时传值呢?还是传引用?程序运行永远都是在栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传对象本身。

Java在方法调用传递参数时,因为没有指针,所以它都是进行传值调用

PS:堆和栈中,栈是程序运行最根本的东西。程序运行可以没有堆,但是不能没有栈。而堆是为栈进行数据存储服务,说白了堆就是一块共享的内存。不过,正是因为堆和栈的分离的思想,才使得Java的垃圾回收成为可能。

原文地址:http://www.manongjc.com/article/431.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM运行原理及Stack和Heap的实现过程 的相关文章

  • 从 Intellij 在远程主机上部署/运行 jvm 应用程序

    是否可以在 intellij 的远程服务器上部署 运行 出于测试目的 独立的 Java 应用程序 我并不是要连接到已经运行的 JVM 而是要从 intellij 在远程主机上启动一个新的 JVM 就像它在我的本地计算机上运行一样 目前没有内
  • Java 调试器:是否可以有选择地挂起线程?

    在我过去作为 C C 程序员的生活中 在某些平台和调试器组合上可以选择性地挂起线程 到达断点后 可以发出命令 或单击 GUI 中的内容 来冻结 解除冻结 挂起 唤醒 线程 在执行进一步的步骤 下一步 运行 继续命令时 挂起的线程将不会执行任
  • 显示JVM中当前运行的所有线程组和线程

    所以我的任务是显示所有线程组以及当前在 JVM 中运行的属于这些组的所有线程 输出时应首先显示线程组 然后在下面显示该组中的所有线程 这是针对所有线程组完成的 目前 我的代码将仅显示每个线程组 然后显示每个线程 但我不确定如何达到我所描述的
  • Jprofile可以连接到docker中运行的JVM

    我是 JProfiler 的新手 我最近遇到了一个问题 我的Java应用程序在docker中运行 这意味着JVM在docker中运行 但我的jprofile安装在主机上 我知道 jprofiler 必须连接到 JVM 那么 jprofile
  • 当 Java 中的集合超出容量时会发生什么?

    我有一个服务 它将所有对其进行的调用暂存在内存中 因为我们不想丢失数据 同时我们需要该服务因任何外部依赖项 例如数据库 而失败 然后 这些分阶段的调用会在后台例行接收和处理 如果出于任何原因 如果调用太多并且内存不足 我们就需要警惕 所以
  • STS 无法在我的计算机上启动

    我试图在 eclipse 上设置 Spring mvc 项目 基本项目进展顺利 但是使用 Restful 服务 Jersey 等开始出现许多与依赖项相关的错误 所以我打算转到STS 我正在使用 STS 2 9 2 它给我 无法创建java虚
  • 如何计算Java数组的内存大小?

    我知道如何通过添加三个部分来计算Java对象的内存大小 标头 属性 引用 我还知道Java数组也是一个对象 但是当我读到 Understanding the JVM Advanced Features and Best Practices
  • Intellij Idea 使用什么 JVM 来启动?

    我是 Eclipse 用户 最近决定尝试 Intellij Idea 我的操作系统是 Ubuntu 12 使用 Eclipse 时 可以通过在 eclipse ini 中指定来轻松选择用于启动 Eclipse 的 JVM http wiki
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • jvm 如何以及何时何地更改 Linux 的最大打开文件值?

    在linux中 每个登录用户的每个进程的最大打开文件数有限制 如下所示 ulimit n 1024 当我学习java nio时 我想检查这个值 因为channel在Linux中也是一个文件 所以我编写了一个客户端代码来不断创建socketC
  • Scala REPL 中的递归重载语义 - JVM 语言

    使用 Scala 的命令行 REPL def foo x Int Unit def foo x String Unit println foo 2 gives error type mismatch found Int 2 required
  • Java 类:匿名类、嵌套类、私有类

    有人能解释一下Java中匿名类 嵌套类和私有类之间的区别吗 我想知道与每个相关的运行时成本以及每个编译器的方法 这样我就可以掌握哪个最适合用于例如性能 编译器优化的潜力 内存使用以及其他 Java 编码人员的普遍可接受性 我所说的匿名类是指
  • 如何使用 Java 引用释放 Java Unsafe 内存?

    Java Unsafe 类允许您按如下方式为对象分配内存 但是使用此方法在完成后如何释放分配的内存 因为它不提供内存地址 Field f Unsafe class getDeclaredField theUnsafe Internal re
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • 容器中的 JVM 计算处理器错误?

    最近我又做了一些研究 偶然发现了这一点 在向 OpenJDK 团队抱怨之前 我想看看是否有其他人观察到这一点 或者不同意我的结论 因此 众所周知 JVM 长期以来忽略了应用于 cgroup 的内存限制 众所周知 现在从 Java 8 更新某
  • Scala 为了在 JVM 上运行做出了哪些妥协?

    Scala 是一种很棒的语言 但我想知道如果它有自己的运行时 如何改进 IE 由于 JVM 的选择 做出了哪些设计选择 我所知道的两个最重要的妥协是 类型擦除 http java sun com docs books tutorial ja
  • 测量 tomcat 的排队请求数

    因此 使用tomcat 您可以设置acceptCount值 默认为100 这意味着当所有工作线程都忙时 新连接被放置在队列中 直到队列满 之后它们被拒绝 我想要的是监视此队列中项目的大小 但无法确定是否有办法通过 JMX 获取此值 即不是队
  • Java中的整数缓存[重复]

    这个问题在这里已经有答案了 可能的重复 奇怪的Java拳击 https stackoverflow com questions 3130311 weird java boxing 最近我看到一个演示 其中有以下 Java 代码示例 Inte
  • 使用适用于 API v2 的 Dropbox Java SDK 时出现 SSLHandshakeException

    In a XPages我想使用的应用程序适用于 API v2 的 Dropbox Java SDK 2 1 2 获取有关我的 Dropbox 帐户的信息 以下代码用于检索相应的帐户对象 String atoken DbxRequestCon
  • Android java.exe 以非零退出值 1 结束 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我尝试过查看类似的解决方案 但没有解决方案有效 我以前运行应用程序没有问题 但我的新应用程序突然开始给我带来问题 当我尝试运行它时总是

随机推荐

  • wxSearchCtrl类使用指南

    wxSearchCtrl类使用指南 wxSearchCtrl是wxWidgets库中的一个类 它提供了一个搜索框控件 允许用户输入关键字进行搜索 在本文中 我们将介绍如何使用wxSearchCtrl以及它的一些常见用法 基本使用方法 要使用
  • 【c++类的默认六个成员函数详解】

    类的六个默认成员函数 构造函数 析构函数 拷贝构造 赋值运算符重载 取地址运算符重载 const修饰的取地址运算符重载 为什么要有这些默认成员函数 如果一个类 在初始化之前就调用了打印函数 则会导致输出的是一个随机值 为了避免这种情况 所以
  • windows程序逆向笔记(一)

    1 吾爱破解 l 按钮 程序运行的日志 插件加载的信息查看 e 按钮 模块信息 程序加载的所有模块 库 都可以看到路径等 双击就可以看到基地址 m 按钮 内存信息 对于 e按钮中 的各个模块的基地址等 t 按钮 线程信息 w 按钮 窗口信息
  • websocket 在 react中的使用全过程

    文章目录 前言 一 前端调用代码 二 前后端联调中的问题 1 连接成功之路 1 完全没成功 2 进入onopen 但是没数据 2 神奇的 userId 三 运用到项目中发现的问题 总结 前言 前一段时间需要做一个关于监控服务器的需求 如果某
  • Java常见的几种设计模式

    单例设计模式 一个类只允许创建一个对象 或者实例 那这个类就是一个单例类 这种设计模式就叫做单例设计模式 1 如何实现一个单例 构造函数需要是 private 访问权限的 这样才能避免外部通过 new 创建实例 考虑对象创建时的线程安全问题
  • 密码学课设实验——序列密码c++实现

    一 实验目的 通过实现简单的线性反馈移位寄存器 LFSR 理解LFSR的工作原理 本原多项式的重要意义 二 实验内容 1 利用C C 语言实现给定的LFSR 2 通过不同初始状态生成相应的序列 并观察它们的周期有什么特点 3 利用生成的序列
  • git 中获取短的 commit hash 值

    本文摘至 http www open open com lib view open1328070367499 html Git 很聪明 它能够通过你提供的前几个字符来识别你想要的那次提交 只要你提供的那部分 SHA 1 不短于四个字符 并且
  • which——查看所使用的一系列命令的程序文件的存放位置

    which命令 1 作用 查看所使用的一系列命令的程序文件的存放位置 2 语法 which 要查找的命令
  • 字节跳动实习记录

    秋招 秋招能拿到字节跳动offer是我没有想到的 暑期只是拿到深圳一家小公司的offer 没有大厂实习经验 秋招迅雷一面挂 腾讯二面挂 能拿到的只有富途和深信服的offer 本打算去富途 但是后面又接到字节跳动的面试通知 原来笔试过了 但是
  • STM32 DMA传输 中断方式配置 源代码

    stm32单片机源程序 include pbdata h void RCC Configuration void void GPIO Configuration void void NVIC Configuration void void
  • jenkins 集成单元测试

    1 jenkins 集成单元测试 1 1先来一张图 趋势图和最新测试结果 出现的前提必须有一次成功的测试通过才能出现 1 2 点击红色 可以看到具体那个单元测试类报错 点到具体的测试类 会显示对应方法 和错误原因 2 配置 pip流水线代码
  • Mysql5.7报错get db conn fail this authentication plugin is not supported

    系统环境CentOS 6 x Mysql5 7 1 前言 在部署open falcon的时候 第一启动有很多模块都失败 查看log日志有如下报错 2019 01 04 10 33 13 db go 22 g InitDB get db co
  • 完全平方数算法题

    题目描述 对于一个序列 牛牛每次可以将序列中任意一个位置上的数乘上任意一个质数 现在他想知道至少需要多少次操作才能使得该序列中的任意两个不同位置的数相乘都为完全平方数 完全平方数 对于x 若其可以写成 i i x i i x
  • 目标检测——Bridging the Gap Between Anchor-based and Anchor-free Detection via ATSS

    question1 1 什么是anchor based anchor free answer 1 目标检测算法一般可分为anchor based anchor free 两者融合类 区别就在于有没有利用anchor提取候选目标框 2 A a
  • QT学生信息管理系统

    QT学生信息管理系统 项目描述 效果图 登录页面 管理员页面 用户页面 数据库表 用户表 学生表 项目描述 使用QT5 14和SQLite3 本项目分为登录界面 管理员界面 用户界面等界面 使用QStackedLayout实现页面布局及切换
  • 10大网络安全攻击手段及防御方法总结(下)

    6 分布式拒绝服务 DDOS DDoS攻击本身不能使恶意黑客突破安全措施 但会令网站暂时或永久掉线 相关数据显示 单次DDOS攻击可令小企业平均损失12 3万美元 大型企业的损失水平在230万美元左右 DDoS旨在用请求洪水压垮目标Web服
  • JAVA求解【乱序整数序列两数之和绝对值最小】

    题目 给定一个随机的整数 可能存在正整数和负整数 数组 nums 请你在该数组中找出两个数 其和的绝对值 nums x nums y 为最小值 并返回这个两个数 按从小到大返回 以及绝对值 每种输入只会对应一个答案 但是 数组中同一个元素不
  • 移动端H5页面在微信浏览器内audio无法自动播放问题解决

    相信许多小伙伴都遇见过这话种情况 在微信浏览器内添加的audio 无法自动播放 之前写过好多那种活动页添加的背景音乐都可以自动播放 直到后来ios 增加了限制就出现了这个问题 怎么解决的只需给audio标签增加一个属性就可以解决如下图
  • 二、MySQL入门

    1 如何查看MySQL是否运行 1查看进程 root sc mysql ps awx grep mysqld 12953 pts 1 S 0 00 bin sh usr local mysql bin mysqld safe datadir
  • JVM运行原理及Stack和Heap的实现过程

    Java语言写的源程序通过Java编译器 编译成与平台无关的 字节码程序 class文件 也就是0 1二进制程序 然后在OS之上的Java解释器中解释执行 而JVM是java的核心和基础 在java编译器和os平台之间的虚拟处理器 注 本网