Java的内存机制

2023-11-11

1.Java的内存机制

 Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域比如,在函数A中调用函数B,在函数B中定义变量a,变量a的作用域只是函数B,在函数B运行完以后,变量a会自动被销毁。分配给它的内存会被回收,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

  堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

代码实例Test01:单个对象创建

class Person{
    String name;
    int age;
    public void tell(){
        System.out.println("姓名:"+name+"年龄"+age);
    }
}

public class Test01 {
    public static void main(String[] args) {
        Person per=new Person();
    }
}

在上述程序中实例化了一个对象per,在实例化对象的过程中需要在内存中开辟空间,这其中就包括栈内存和对内存。具体的内存分配如下图所示:

我们可以从上图中发现,对象名称per被保存在了栈内存中(更加准确的说法是,在栈内存中保存的是堆内存空间的访问地址),而对象的具体内容,比如属性name和age,被保存在了堆内存中。因为per对象只是被实例化,还没有具体被赋值,所以都是默认值。字符串的默认值为null,int类型的默认值为0。前面也已经提到,堆内存空间必须使用new关键字才能开辟。

代码实例Test02:多个对象创建

class Person{
    String name;
    int age;
    public void tell(){
        System.out.println("姓名:"+name+",年龄:"+age);
    }
}

public class Test02 {
    public static void main(String[] args) {
        Person per1=new Person();
        Person per2=new Person();
        
        per1.name="张三";
        per1.age=30;
        per2.name="李四";
        per2.age=33;
        
        per1.tell();
        per2.tell();
    }
}

关键概念:类跟数组一样,都是属于引用类型,引用类型就是指一堆对内存可以同时被多个栈内存指向。下面来看一下引用传递的简单实例。

代码实例Test03:对象引用传递1

class Person{
    String name;
    int age;
    public void tell(){
        System.out.println("姓名:"+name+",年龄:"+age);
    }
}

public class Test03{
    public static void main(String[] args) {
        Person per1=new Person();
        Person per2=per1;
        
        per1.name="张三";
        per1.age=30;
        per2.age=33;
        
        per1.tell();
        per2.tell();
    }
}

程序运行结果为:

姓名:张三,年龄:33
姓名:张三,年龄:33

从程序的运行结果可以发现,两个对象输出的内容一样,实际上所谓的引用传递,就是将一个堆内存空间的使用权交个多个栈内存空间,每个栈内存空间都可以修改堆内存空间的内容,此程序的内存分配图如下所示:

注意:上述实例中对象per2没有堆内存空间,这是因为对象per2只进行了声明操作,也没有进行实例化操作。只有使用new关键字实例化以后才会有对内存空间。

代码实例Test04:对象引用传递2

class Person{
    String name;
    int age;
    public void tell(){
        System.out.println("姓名:"+name+",年龄:"+age);
    }
}

public class Test04 {
    public static void main(String[] args) {
        Person per1=new Person();
        Person per2=new Person();

        per1.name="张三";
        per1.age=30;
        per2.name="李四";
        per2.age=33;
        per2=per1;
        
        per1.tell();
        per2.tell();
    }
}

上述程序运行结果为:

姓名:张三,年龄:30
姓名:张三,年龄:30

从程序的输出结果可以发现可Test03一样。不过内存分配发生了一些变化,具体如下所示:

注意点:

  1. Java本身提供垃圾收集机制(Garbage Collection,GC),会不定期施放不用的内存空间,只要对象不用了,就会等待GC释放空间,如上面堆内存中的name="李四";age=33。
  2. 一个栈内存只能指向一个对内存空间,如果要想再指向其他的堆内存空间,则必须先断开已有的指向才能分配新的指向。

java中常用的内存区域

在java中主要存在4块内存空间,这些内存的名称及作用如下:

  1. 栈内存空间:保存所有的对象名称(更准确地说是保存了引用的堆内存空间的地址)
  2. 堆内存空间:保存每个对象的具体属性内容。
  3. 全局数据区:保存static类型的属性。
  4. 全局代码区:保存所有的方法定义。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java的内存机制 的相关文章

  • 在 Java 中克隆对象 [3 个问题]

    这样做会调用Asub的clone方法吗 或者Asub深度克隆是否正确 如果没有的话 有没有办法通过这种方法对Asub进行深度克隆呢 abstract class Top extends TopMost protected Object cl
  • Spring应用中Eureka健康检查的问题

    我正在开发一个基于 Spring 的应用程序 其中包含多个微服务 我的一个微服务充当尤里卡服务器 到目前为止一切正常 在我所有其他微服务中 用 EnableEurekaClient 我想启用这样的健康检查 应用程序 yml eureka c
  • 为什么 JTables 使 TableModel 在呈现时不可序列化?

    所以最近我正在开发一个工具 供我们配置某些应用程序 它不需要是什么真正令人敬畏的东西 只是一个具有一些 SQL 脚本生成功能并创建几个 XML 文件的基本工具 在此期间 我使用自己的 AbstractTableModel 实现创建了一系列
  • 动态选择端口号?

    在 Java 中 我需要获取端口号以在同一程序的多个实例之间进行通信 现在 我可以简单地选择一些固定的数字并使用它 但我想知道是否有一种方法可以动态选择端口号 这样我就不必打扰我的用户设置端口号 这是我的一个想法 其工作原理如下 有一个固定
  • 谷歌应用程序引擎会话

    什么是java应用程序引擎 默认会话超时 如果我们将会话超时设置为非常非常长的时间 会不会产生不良影响 因为谷歌应用程序引擎会话默认情况下仅存储在数据存储中 就像facebook一样 每次访问该页面时 会话仍然永远存在 默认会话超时设置为
  • 在接口中使用默认方法是否违反接口隔离原则?

    我正在学习 SOLID 原则 ISP 指出 客户端不应被迫依赖于他们所使用的接口 不使用 在接口中使用默认方法是否违反了这个原则 我见过类似的问题 但我在这里发布了一个示例 以便更清楚地了解我的示例是否违反了 ISP 假设我有这个例子 pu
  • 从最终实体获取根证书和中间证书

    作为密码学的菜鸟 我每天都会偶然发现一些简单的事情 今天只是那些日子之一 我想用 bouncy castle 库验证 java 中的 smime 消息 我想我几乎已经弄清楚了 但此时的问题是 PKIXparameters 对象的构建 假设我
  • 像 Java 这样的静态类型语言中动态方法解析背后的原因是什么

    我对 Java 中引用变量的动态 静态类型和动态方法解析的概念有点困惑 考虑 public class Types Override public boolean equals Object obj System out println i
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • 如何在用户输入数据后重新运行java代码

    嘿 我有一个基本的java 应用程序 显示人们是成年人还是青少年等 我从java开始 在用户输入年龄和字符串后我找不到如何制作它它们被归类为 我希望它重新运行整个过程 以便其他人可以尝试 的节目 我一直在考虑做一个循环 但这对我来说没有用
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 获取文件的总大小(以字节为单位)[重复]

    这个问题在这里已经有答案了 可能的重复 java 高效获取文件大小 https stackoverflow com questions 116574 java get file size efficiently 我有一个名为 filenam
  • 使用 AsyncTask 传递值

    我一直在努力解决这个问题 但我已经到了不知道该怎么办的地步 我想做的是使用一个类下载文件并将其解析为字符串 然后将该字符串发送到另一个类来解析 JSON 内容 所有部件都可以单独工作 并且我已经单独测试了所有部件 我只是不知道如何将值发送到
  • 关键字“table”附近的语法不正确,无法提取结果集

    我使用 SQL Server 创建了一个项目 其中包含以下文件 UserDAO java public class UserDAO private static SessionFactory sessionFactory static se
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 我如何在java中读取二进制数据文件

    因此 我正在为学校做一个项目 我需要读取二进制数据文件并使用它来生成角色的统计数据 例如力量和智慧 它的设置是让前 8 位组成一个统计数据 我想知道执行此操作的实际语法是什么 是不是就像读文本文件一样 这样 File file new Fi
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 长轮询会冻结浏览器并阻止其他 ajax 请求

    我正在尝试在我的中实现长轮询Spring MVC Web 应用程序 http static springsource org spring docs 2 0 x reference mvc html但在 4 5 个连续 AJAX 请求后它会
  • 双枢轴快速排序和快速排序有什么区别?

    我以前从未见过双枢轴快速排序 是快速排序的升级版吗 双枢轴快速排序和快速排序有什么区别 我在 Java 文档中找到了这个 排序算法是双枢轴快速排序 作者 弗拉基米尔 雅罗斯拉夫斯基 乔恩 本特利和约书亚 布洛赫 这个算法 在许多数据集上提供

随机推荐

  • 记录STM32各类串口中断实验

    STM32F407VG使用cubemx LL库 波特率115200 一位停止位 无校验 单片机初始化串口一 PA8高速推挽输出 使用逻辑分析仪100M采样捕获各类串口中断触发时的波形 首先是喜闻乐见的RXNE 理论是只要串口成功接收一byt
  • Cache 和 Buffer 有什么区别

    Cache 和 Buffer 有什么区别 转载 talkwithtrend https mp weixin qq com s YsEOBVS7fXgrGXnXH1I0MQ Cache和Buffer简单的说 Cache是加速 读 而buffe
  • android自定义可缩放,移动图像裁剪框

    在实际项目中 经常要制作一个简易的图像裁剪功能 即获取一张图片 并用一个遮罩层选择目标范围并截取保存的功能 如下图所示 在此分享下该自定义视图的制作过程 需求说明 整一个视图包含一个透明的遮罩层 一个透明带白色边框的矩形 要实现的功能是 点
  • oracle 问题 :Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正确结束

    使用mysql时使用的sql语句常有 结尾的语句 但oracle中不能出现 结尾 因为oracle解析器很严谨 不支持 结尾语句解析
  • C基础day6(2023.7.6)

    一 Xmind整理 二 课上练习 练习1 循环嵌套 三个循环结构可以任意嵌套 include
  • Python爬虫分析唯品会商品数据 +数据可视化

    目录 前言 数据来源分析 1 明确需求 2 抓包分析 通过浏览器自带工具 开发者工具 代码实现步骤 发送请求 gt 获取数据 gt 解析数据 gt 保存数据 发送请求 解析数据 保存数据 数据可视化 先读取数据 泳衣商品性别占比 商品品牌分
  • Springmvc+mybatis+Dubbo+ZooKeeper+Redis+KafKa

    开发工具 1 Eclipse IDE 采用Maven项目管理 模块化 2 代码生成 通过界面方式简单配置 自动生成相应代码 目前包括三种生成方式 增删改查 单表 一对多 树结构 生成后的代码如果不需要注意美观程度 生成后即可用 技术选型 只
  • Androidstudio快捷操作之多选

    如图 想要批量复制属性名 不需要一个一个的复制 只需按住alt 鼠标左键从上往下拉 将光标定位在每个属性名的前面 再按ctrl w就可以选中所有光标后面的单词了
  • QT里使用sqlite的问题,好多坑

    1 我使用sqlite 开发机上好好的 测试机上却不行 后来发现是缺少驱动 Driver not loaded Driver not loaded 代码检查了又检查 发现应该是缺少dll文件 系统不提示 是自己使用 QMessageBox
  • c语言基础五子棋,十分的易懂理解,详细解释,容易上手

    前言 提示 经过b站和视频学习后编程 提示 以下是本篇文章正文内容 下面案例可供参考 文章目录 前言 五子棋 头文件 展示棋盘 display 下棋 PlayMove 主体函数 game 完整代码 五子棋 本篇博客主要写了关于c语言的五子棋
  • MySQL主从搭建-Centos实战

    目录 一 规划说明 二 主节点安装MySQL 1 下载MySQL和安装 2 启动Mysql 设置root密码 允许远程登录 三 副节点安装MySQL 参考主节点 四 主节点配置 1 配置my cnf 修改默认存储目录为指定目录 data 下
  • 解决SQL查询总是超时已过期

    解决SQL查询总是超时已过期 在WIN8里提示 OLE DB 或 ODBC 错误 查询超时已过期 HYT00 1 由于数据库设计问题造成SQL数据库新增数据时超时 症状 Microsoft OLE DB Provider for SQL S
  • web前端页面适配方法

    流式布局 就是百分比布局 非固定像素 内容向两侧填充 理解成流动的布局 称为流式布局 视觉窗口 viewport 是移动端特有 这是一个虚拟的区域 承载网页的 承载关系 浏览器 gt viewport gt 网页 适配要求 1 网页宽度必须
  • c++基础十一(跳转语句)

    跳转语句 1 break 2 continue 3 goto 1 break 作用 跳出循环结构和选择结构 1 switch语句中 用于终止case并跳出switch语句 2 在循环结构中 用于跳出当前循环 3 在嵌套循环语句中 跳出最近的
  • 企业微信 => 接入第三方vue应用 第三阶段:企业微信使用JSSDK

    目录 使用说明 官方文档不会告诉你的内容 都是会踩的坑 一 我采用的混入方法去使用这个官方SDK 二 可能会遇到的坑 前提 我们开发的是三方应用 不是内部应用 使用说明 所有的JS接口只能在企业微信应用的可信域名下调用 包括子域名 且可信域
  • 深度学习环境搭建( Tensorflow & PyTorch)

    前言 硬件配置 基础软件 1 安装VC redist x64 2 安装显卡驱动并确定算力 3 确认cuda版本 4 安装CUDA 配置cudnn 5 安装Anaconda 6 安装PyCharm 深度学习框架Tensorflow安装 深度学
  • 复习之linux系统中的权限管理

    1 权限的查看及读取 1 权限的查看 ls l file 查看文件的权限 ls ld dir 查看目录权限 2 权限的读取 文件的属性叫做文件的元数据 元数据 Metadata 又称中介数据 中继数据 为描述数据的数据 data about
  • HTML爱心表白代码,亲测有效,独一无二!福利来啦!

    发福利啦 小编最近搜集了好几个表白代码 感兴趣可以点进主页看看哟 如果觉得文章不错 还请一键三联 不定时发布各种全免费的独一无二的代码 这次我们来分享跳动的爱心的代码 网上有很多 但是个人觉得我这个比较温馨一点 背景也好看
  • springboot框架介绍,让我们深入的了解

    Spring Boot是一种用于快速构建基于Spring框架的Java应用程序的开源框架 它旨在简化Spring应用程序的开发过程 通过提供一种约定优于配置的方式 让开发人员能够快速搭建起一个可独立运行的 可部署的 易于扩展的应用 Spri
  • Java的内存机制

    1 Java的内存机制 Java 把内存划分成两种 一种是栈内存 另一种是堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配 当在一段代码块定义一个变量时 Java 就在栈中为这个变量分配内存空间 当超过变量的