当前位置: 首页 > ai >正文

JVM管理数据的方式

JVM有极其强大的内存管理机制,在JAVA中所有申请的资源都由JVM自动清理,而无需手动销毁。

1.JVM管理数据的机制

在JVM中,内存由栈区、堆区、方法区、本地方法栈等组成。

栈区是存储局部变量和方法调用的地址;堆区用于存储对象实例和各种数组,堆区上的任何资源都由JVM自动清除。方法区由于存储各种方法、各种类中的方法以及静态变量等;而本地方法栈主要由于存主函数中的方法。

2.引用数据类型的存储方式

在Java中,引用类型(对象、数组、字符串等)的存储涉及两个部分:引用本身和实际对象。

引用本身的存储位置

         存储在Java虚拟机栈的栈帧局部变量表中

         包括方法参数和方法内定义的局部变量

  1. 局部变量中的引用

  2. 对象成员变量中的引用:存储在堆内存中(作为对象实例数据的一部分)

  3. 静态变量中的引用:存储在方法区

注意:一切引用类型指向的实际对象(包括普通对象、数组、字符串对象等)都存储在堆内存(Heap)中。但是也有特殊情况:

字符串常量:

基本类型数组:

  • 字符串字面量(如"hello")存储在字符串常量池

  • Java 7之前位于方法区,Java 7及之后位于堆内存

  • 数组对象本身在堆中,元素如果是基本类型则直接存储值

int[] arr = new int[10],整个数组在堆中

对象数组:

  • 数组对象在堆中,元素存储的是指向其他对象的引用

String[] arr = new String[10],数组在堆中,元素初始为null

下面重点讨论string类的存储方式。JAVA为了提高性能,直接量字符串会缓存在字符串常量池中。对于重复出现的字符串直接量,JVM会优先在常量池中寻找,找到了就直接返回该对象的引用,达到重复使用内存的目的。

String s1 = "123abc";
String s2 = "Hello World";
String s3 = "Hello World";
System.out.println(s1 == s2);
System.out.println(s1 == s3);
String s4=new String("Hello World");
System.out.println(s1 == s4);

在JAVA中,两个字符串做==比较时,比较的是两个字符串的地址而不是内容(如果想比较内容应该调用String类中的equal方法)。所以可以看到输出的结果是false true false。这样就验证了s3的确是复用了s2的"Hello World"。让人意外的是第三个也是false,明明都是"Hello world"怎么这里地址就不同呢?

其实new出来的对象都不会复用s2,而是在堆区新开辟一个"hello"的空间,所以s2和s4的地址必然不相同。可是既然s2和s3共用一个字符串,那万一哪天s2销毁了然后又想访问s3怎么办呢?它之所以敢这样复用,是因为在堆区一切的资源都由JVM来清理,它的底层是用了引用计数来记录有几个复用,当为0时才会自动销毁,这就无需担心能否访问的问题了。

      

所以整个过程就是,首先s1里面是"123abc",先到字符串常量池中找,没找到就为它新开辟一个string;s2创建的时候也没有,那就新开辟;s3创建的时候找了,在字符串找到了就直接用s2的,而然后就把字符串常量池的那个地址拷贝过来到它的栈内存的地址;s4由于是实例化出来的对象,它就直接在堆区新开辟空间,栈内存中是不存任何东西的。

3.基本类型的存储方式

Java中的基本数据类型的存储方式与引用类型不同,它们的存储位置取决于使用场景。

(1)方法体中的局部变量

存放在JVM栈区

public void method() {int a = 10;       // 存储在栈中double b = 0.5;  // 存储在栈中
}

(2)对象成员变量中的基本类型

作为对象实例的一部分,里面的基本变量存储在

class A {int x;          // 当创建A对象时,x存储在堆中boolean flag;   // 存储在堆中
}

(3)静态变量中的基本类型

存储在方法区.静态变量(包括基本类型和引用)的变量名和值直接存储在方法区/元空间,只有一份

下面进行验证:

public class StaticVar {int a;static int b;StaticVar(){a++;b++;}void Show(){System.out.println(a+" "+b);}
}public class StaticDemo {public static void main(String[] args) {StaticVar demo1 = new StaticVar();demo1.Show();StaticVar demo2 = new StaticVar();demo2.Show();StaticVar demo3 = new StaticVar();demo3.Show();}
}

类中定义了一个整形变量a和静态变量b,在构造方法中给a和b分别进行++操作。接着创建了三个实例对象,每创建一个输出a和b的值。运行结果输出了1 1/1 2/1 3。

在进行demo1的实例化时,毫无疑问a、b分别进行了++,所以输出1 1;在进行demo2实例化时,b进行了++而a没有,这是因为demo2独有的a,默认从0开始,而b是静态变量,存在方法区,所以在原来1的基础上再加1;同样的demo3也是a从0加到1,b从2加到3。

基本类型由于直接存储在栈中或作为对象的一部分连续存储有优势:访问速度更快;内存占用更小;没有垃圾回收开销。

4.JVM管理内存的优势和不足

JVM采用自动内存管理(垃圾回收机制),开发者无需手动分配或释放内存。内存分为堆、方法区、虚拟机栈、本地方法栈和程序计数器。堆是垃圾回收的主要区域,存放对象实例;方法区存储类信息、常量等;栈存储局部变量和方法调用。

垃圾回收器通过标记-清除、复制、标记-整理等算法自动回收不再使用的对象。分代收集策略将堆分为新生代和老年代,针对不同生命周期对象采用不同回收算法。

JVM:全自动垃圾回收,无需开发者干预,但可能因GC暂停影响性能。垃圾回收可能导致不可预测的停顿,尤其在Full GC时。严格划分内存区域,对象仅能分配在堆上(逃逸分析优化可能例外)。内存问题相对少见,但GC调优复杂(如选择回收器、调整堆大小)。

而在C++中支持手动内存管理,通过new/deletemalloc/free显式控制内存分配与释放。内存分为栈、堆、全局/静态存储区等。栈用于局部变量和函数调用,自动管理;堆由程序员手动管理,动态分配的内存需手动释放,否则可能导致内存泄漏。同时为了减轻程序员的负担,在C++11引入智能指针辅助自动管理堆内存,基于RAII(资源获取即初始化)原则减少手动释放的负担,但核心仍依赖开发者控制资源生命周期。

C++:以手动管理为主,智能指针提供部分自动化支持,灵活性高但易出错。无GC开销,实时性更强,但手动管理不当会引发内存泄漏或野指针。对象可分配在栈或堆,栈对象生命周期与作用域绑定,效率更高。需处理内存泄漏、悬垂指针等问题,调试工具(如Valgrind)常被使用。

综上所述,JVM适合开发效率优先、高复杂度的业务系统(如Web应用),避免手动管理风险。C++:适合性能敏感、实时性要求高的场景(如游戏引擎、嵌入式系统),需精细控制内存。

    JVM通过这些机制高效地管理数据,同时提供自动内存管理功能,大大减轻了程序员的负担。

    http://www.xdnf.cn/news/17519.html

    相关文章:

  • 剧本杀小程序系统开发:推动行业数字化转型新动力
  • Linux中DNS系统搭建与配置指南(配实验步骤与注释)
  • 在 .NET Core 5.0 中启用 Gzip 压缩 Response
  • Tricentis Tosca:现代软件测试的自动化利器
  • 企业级 IT 运维服务平台数据备份方案:基于 rsync 的自动化实现
  • AI生成代码时代的商业模式重构:从“软件即产品”到“价值即服务”
  • 云原生环境Prometheus企业级监控
  • Notepad++ 插件开发实战:从理念到落地的探索
  • 嵌入式第二十五天(基于Linux操作系统的编程-文件操作)
  • 大模型提示词工程实践:大语言模型文本转换实践
  • 【读代码】微软开源Agentic-RAG深度解析
  • execjs执行js报错, subprocess.py编码问题
  • Ignite端口管理组件GridPortProcessor全解析
  • Linux系统编程——基础IO
  • 《录井管理与工程》书籍第一章要点及相应思考
  • 虚幻GAS底层原理解剖十 (网络)
  • 深度剖析 Linux 信号:从基础概念到高级应用,全面解析其在进程管理与系统交互中的核心作用与底层运行机制
  • Orange的运维学习日记--39.Nginx详解与服务部署
  • 【liunx】web高可用---nginx
  • GSON 框架下百度天气 JSON 数据转 JavaBean 的实战攻略
  • ZooKeeper和Reids做分布式锁的区别?
  • Notepad--:国产跨平台文本编辑器,Notepad++ 的理想替代方案
  • 车载软件架构 --- 车辆量产后怎么刷写Flash Bootloader
  • 【数据结构入门】二叉树(1)
  • Redis7 GEO功能介绍与电商场景案例解析
  • Android模块化架构深度解析:从设计到实践
  • HTML5中华美食网站源码
  • (Arxiv-2025)Phantom-Data:迈向通用的主体一致性视频生成数据集
  • LangChain框架之 invoke() 方法
  • 【SpringBoot】02 基础入门-什么是Spring Boot?:Spring与SpringBoot