java对象内存模型_Java对象的内存模型

众所周知,函数调用在内存中是通过压栈,退栈实现的,而Java的方法调用则是在JVM栈中通过栈帧实现的,且所有的Java对象都只在堆上分配内存.那么一个Java对象在堆内存里到底长啥样呢?实际上,当一个对象在内存中被创建的时候,它只不过是一串0和1而已.编译器会维护一张表,这张表用来存储对象中的每一个成员变量所在位置的偏移量(offset).这样,通过查这张表,JVM就能知道每一个成员变量相对于其起始地址所在的位置了.

来看这样一个例子.我们定义一个名为 Base 的类,它没有任何的成员方法,只有两个成员变量x和y.Base 对象的内存模型如下图所示:

5ce66e0100bd28ede247dfeac86d9b16.png

然后我们从Base类派生一个名为 Derived 的子类,则 Derived 对象的内存模型如下:

b8977cdacee6ecb558cbdb6f00bdc023.png

可以看到,子类的内存模型实际上就是在父类的基础上添加了子类特有的成员变量而已.这样设计的好处是,如果有一个 Base 类型的引用指向了 Derived 对象,那么由于 Derived对象的内存模型中包含了其父类 Base,因而 Base 类对于其子类 Derived 是可见的. 这样一来,任何通过Base引用操作 Derived 对象的调用都是安全的.

啥叫安全呢?例如上面这个例子,编译器会维护一张保存有成员变量offset的表,这张表是这么写的:x变量在第1个位置,y变量在第2个位置,z变量在第3个位置.(当然实际中肯定不是第几个位置这么简单,编译器会根据变量的数据类型确定其offset,如,一个int偏移4字节,一个double偏移8字节).当我们通过Base引用来引用Derived中的成员时,编译器就会去找这个对象中的第几个位置.比如调用derived.x 会去找第一个位置,derived.z,则会去找第三个位置.因为子类Derived中包含了父类的x,y变量,而且次序正好排在x,y之后,所以derived.z可以被成功执行.

按照这个逻辑,方法也可以放在每个对象的起始位置:

be51ee2ee23a136fce0c4e0aa7abcca5.png

不过,这么干是非常低效的.如果一个类有很多的方法,那么就要在起始位置保存大量的数据,并且每个对象都会重复地保存这些函数代码.这样对象构造起来就慢,造成空间和时间上的性能浪费.

解决这个问题的一个办法是,为每一个类创建一个虚表(virtual table),这张表里保存了这个类中所有的方法代码.而对于这个类的对象,则在其内存的起始位置中保存一个指向此表的指针.这样一来,多个对象就能共享一份方法代码了.

e503dea62d922bd29cfe3f444549a265.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471574.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fastapi 请求文件 / 表单 / 处理错误 / 路径操作配置 / jsonable_encoder

文章目录1. File 参数2. 多文件上传3. 请求表单与文件4. 处理错误5. 自定义响应头6. 自定义异常处理器7. 覆盖默认异常处理器8. 使用 RequestValidationError 的请求体9. 复用 FastAPI 异常处理器10. 路径操作参数配置10.1 status_code,tags10.2 summary&#xff0c…

fastapi PUT更新数据 / PATCH部分更新

文章目录1. PUT 更新2. 用 PATCH 进行部分更新learn from https://fastapi.tiangolo.com/zh/tutorial/body-updates/1. PUT 更新 注意,put 没有指定的值,会被重置为默认值 from typing import List, Optionalfrom fastapi import FastAPI from fastap…

Chrome 扩展 最近的历史 HistoryBar v1.1

说明 以前用过一段时间傲游浏览器,渐渐的习惯了它的鼠标手势和一些细微的人性化的功能。比方地址栏左边的“近期訪问的页面”button。能够方便的找到近期 20 条历史记录。 但后来因为某些原因又回到了 Chrome 的怀抱,于是就没有了这些不起眼但非常好用的…

LeetCode 2047. 句子中的有效单词数

文章目录1. 题目2. 解题1. 题目 句子仅由小写字母(a 到 z)、数字(0 到 9)、连字符(-)、标点符号(!、. 和 ,)以及空格( )组成。 每个句子可以根据空格分解成 …

LeetCode 2048. 下一个更大的数值平衡数(枚举)

文章目录1. 题目2. 解题1. 题目 如果整数 x 满足:对于每个数位 d ,这个数位 恰好 在 x 中出现 d 次。 那么整数 x 就是一个 数值平衡数 。 给你一个整数 n ,请你返回 严格大于 n 的 最小数值平衡数 。 示例 1: 输入&#xff1a…

LeetCode 2049. 统计最高分的节点数目(DFS)

文章目录1. 题目2. 解题1. 题目 给你一棵根节点为 0 的 二叉树 ,它总共有 n 个节点,节点编号为 0 到 n - 1 。 同时给你一个下标从 0 开始的整数数组 parents 表示这棵树,其中 parents[i] 是节点 i 的父节点。 由于节点 0 是根,所…

python源文件编码的含义_【原创】Python 源文件编码解读

以下内容源于对 PEP-0263 的翻译和解读,同时给出了一些网上网友的说法。 我是分割线 PEP 0263 -- Defining Python Source Code Encodings【摘要】给出声明 Python 源文件编码的语法。该编码信息后续会被 Python 解析器用于解析源文件。这种方式增强了对源文件中 U…

MyEclipse中SVN的常见的使用方法

本次主要内容: 一 、导入项目 (Checkout)。从svn资源库检出 二 、更新 (Update) 三、锁(对要修改的文件加锁,防止文件冲突) 四、提交(项目修改后的提交) 五、…

fastapi 路径依赖项Depends / 装饰器依赖dependencies / 全局依赖 / 带 yield 的依赖

文章目录1. 依赖项2. 类作为依赖3. 子依赖项3.1 多次使用同一个依赖项4. 路径操作装饰器依赖项5. 全局依赖项6. 带 yield 的依赖项7. 使用带 yield 上下文管理器作为依赖项learn from https://fastapi.tiangolo.com/zh/tutorial/dependencies/ 1. 依赖项 只能传给 Depends 一…

fastapi 安全性 / APIRouter / BackgroundTasks / 元数据 / 测试调试

文章目录1. 例子2. 获取当前用户3. 使用密码和 Bearer 的简单 OAuth24. 使用(哈希)密码和 JWT Bearer 令牌的 OAuth25. 多个应用文件5.1 APIRouter6. BackgroundTasks7. 元数据7.1 标题、描述和版本7.2 openapi_tags 标签元数据7.3 OpenAPI URL7.4 文档 …

java json path_Java使用JSONPath解析JSON完整内容详解

JsonPath是一种简单的方法来提取给定JSON文档的部分内容。 JsonPath有许多编程语言,如Javascript,Python和PHP,Java。JsonPath提供的json解析非常强大,它提供了类似正则表达式的语法,基本上可以满足所有你想要获得的js…

LeetCode 2050. 并行课程 III(拓扑排序)

文章目录1. 题目2. 解题1. 题目 给你一个整数 n ,表示有 n 节课,课程编号从 1 到 n 。 同时给你一个二维整数数组 relations ,其中 relations[j] [prevCoursej, nextCoursej] ,表示课程 prevCoursej 必须在课程 nextCoursej 之前…

LeetCode 1521. 找到最接近目标值的函数值(位运算)

文章目录1. 题目2. 解题1. 题目 Winston 构造了一个如上所示的函数 func 。他有一个整数数组 arr 和一个整数 target ,他想找到让 |func(arr, l, r) - target| 最小的 l 和 r 。 请你返回 |func(arr, l, r) - target| 的最小值。 请注意, func 的输入参…

LeetCode 2053. 数组中第 K 个独一无二的字符串(哈希)

文章目录1. 题目2. 解题1. 题目 独一无二的字符串 指的是在一个数组中只出现过 一次 的字符串。 给你一个字符串数组 arr 和一个整数 k ,请你返回 arr 中第 k 个 独一无二的字符串 。 如果 少于 k 个独一无二的字符串,那么返回 空字符串 “” 。 注意…

LeetCode 2055. 蜡烛之间的盘子(前缀和)

文章目录1. 题目2. 解题1. 题目 给你一个长桌子,桌子上盘子和蜡烛排成一列。 给你一个下标从 0 开始的字符串 s ,它只包含字符 * 和 | ,其中 * 表示一个 盘子 ,| 表示一支 蜡烛 。 同时给你一个下标从 0 开始的二维整数数组 que…

策略模式java 用例_java策略模式简单用例

运用java策略模式一个小程序/****/package Strategy;import java.util.Arrays;/*** author HuangRong* Funtion 定义策略*/public interface ComputablesStra {public abstract void printForm();}/****/package Strategy;/*** author HuangRong* Function 为策略模式中的上下文…

LeetCode 2057. 值相等的最小索引

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums ,返回 nums 中满足 i mod 10 nums[i] 的最小下标 i ;如果不存在这样的下标,返回 -1 。 x mod y 表示 x 除以 y 的 余数 。 示例 1: 输入:num…

LeetCode 2058. 找出临界点之间的最小和最大距离(链表)

文章目录1. 题目2. 解题1. 题目 链表中的 临界点 定义为一个 局部极大值点 或 局部极小值点 。 如果当前节点的值 严格大于 前一个节点和后一个节点,那么这个节点就是一个 局部极大值点 。 如果当前节点的值 严格小于 前一个节点和后一个节点,那么这个…

LeetCode 2059. 转化数字的最小运算数(BFS)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums ,该数组由 互不相同 的数字组成。另给你两个整数 start 和 goal 。 整数 x 的值最开始设为 start ,你打算执行一些运算使 x 转化为 goal 。你可以对数字 x 重复执行下述运算&…

又是一年国庆假期最后一天

时间过的真的很快啊,美好的日子已经快过完了,在长假的最后一天,有很多的朋友可能都会抱怨,不想上班了,好想在好好的玩玩。开开心心的过完了假期的前六天,当突然被告知明天就是最后一天,你会有什…