Javer 学 c++(十二):与 JVM 对比篇

总览

主要讲了 c++ 和 Java 两种语言内存空间分布上的不同以及为什么不同

Java 内存区域

先上图

接下来一块一块来讲

一、c++ 中没有的部分

本地方法栈

我们知道本地方法栈里存的是 native 方法的调用栈,也就是底层的 c/c++ 方法

问题一:Java 为什么为什么要调用本地方法?

我们知道 Java 很经典的那句话 "write once, run anywhere",Java 的运行依赖于 JVM。

而 JVM 本质上就是在底层操作系统上又加了一层,才实现了跨平台的能力,但是也带来了一些缺点:

  • 无法直接操作底层硬件资源:比如直接操作内存、文件系统、硬件设备等
  • 性能瓶颈:class 文件是要经过 JVM 来解释执行的,怎么比得过 c++ 编译完二进制直接执行呢?当然 JVM 也做了一些优化,例如 JIT 等

所以需要 native 方法来帮我解决上面的一些问题,JVM 本身是由 c++ 实现的

字节码执行的本质是被一个 c++写的虚拟机转换为机器码来执行

问题二:Java 为什么要有本地方法栈?

个人理解主要的原因:一是需要进行环境隔离,避免相互干扰(虚拟机栈和本地方法栈);二是线程隔离,每个线程都有两个栈,本地方法的执行不会影响 Java 栈。

所以 Java 有native 方法栈,但是 c++因为编译型语言,直接运行在操作系统上,不需要虚拟机,而是由编译器来处理,所以不需要本地方法栈。

程序计数器PC

JVM 中的程序计数器是用来记录当前线程执行的字节码指令地址,存储的是字节码指令的地址而不是机器码地址。

而 c++ 的程序计数器是 CPU 的物理寄存器,由操作系统和硬件直接管理。

这里说点人能听懂的话哈哈哈

我们前面提到了 JVM 其实是在操作系统之上又加了一层,所以原本操作系统本身的 PC 是没法使用的,相当于我们在 JVM 里面手动实现了一个 PC,完毕

二、c++ 和 Java 对比的部分

回顾上一篇,c++ 有四个区域:代码区、全局区、栈区、堆区,然后来比较下

代码区 vs JVM 方法区(元空间)

c++代码区 Java元空间
存放程序的机器指令(编译后的二进制代码) 存放类信息、常量池、静态变量、方法字节码等
代码区是只读的,不可以修改 可以在运行时动态加载类

方法区可以看做 Java 对代码区的拓展,不仅包含代码,还包含了运行时常量池和类的元数据

全局区 vs JVM方法区 + Java堆中的字符串常量池

回顾一下上一篇,全局区里存了什么?

我们依次看下这些数据在 Java 里都存在什么地方呢?

全局变量 or 静态变量:Java 里没有全局这个概念,但是可以认为 static 实现类似功能(类级别),存在方法区中

全局常量: Java 中对应 static final 字段,也是存在于方法区中

字符串常量 :对应字符串常量池 ,最开始在方法区,后面被移动到 堆内存

栈区 vs Java虚拟机栈

本质上是类似的,但是由前面本地方法栈的分析可得:

c++ 的栈是由编译器自动管理的,而 Java 由于 JVM 这一层的原因,是有 JVM 来管理我们的虚拟机栈

堆区 vs JVM 堆

在 c++ 中,此区域由程序员手动管理(new/delete, malloc/free),用于动态分配对象,需要我们手动释放内存,否则会造成内存泄露。

Java 中由 JVM 自动管理,通过 GC 来自动回收内存,不需要程序员管理

c++手动 vs JVM自动

讲到这里了,就再讲讲手动和自动的区别吧

个人理解,手动主要是性能:

  • 没有 GC 开销,包括 GC 停顿以及 GC roots 的扫描
  • 零拷贝优化:直接操作内存地址,减少数据拷贝 包括其他的 cache 对齐等优化

自动主要是容错

  • 手动的话不释放会有内存泄露
  • 对象量很多的话,显式调用太麻烦,很容易出错、遗漏
  • 缓冲区溢出:手动操作越界等等

因为楼主之前一直用的是 Java,其实没有自己去过申请、释放过内存,希望后续的c++学习中能够有更加深入的了解

相关推荐
杨杨杨大侠2 小时前
手搓责任链框架 6:高级应用
java·spring·github
麦兜*2 小时前
MongoDB 高可用部署:Replica Set 搭建与故障转移测试
java·数据库·spring boot·后端·mongodb·spring cloud·系统架构
汤姆yu2 小时前
2025版基于springboot的电影购票管理系统
java·spring boot·后端·电影购票
程序喵大人3 小时前
手写智能指针:带你彻底搞懂 C++ 内存管理的底层逻辑
开发语言·c++·内存管理·智能指针
草莓熊Lotso3 小时前
【C++】详解形参和实参:别再傻傻分不清
c语言·开发语言·c++·经验分享·笔记·其他
悟乙己3 小时前
如何区分 Context Engineering 与 Prompt Engineering
android·java·prompt
头孢头孢3 小时前
基于 EasyExcel + 线程池 解决 POI 导出时的内存溢出与超时问题
java
写不出来就跑路3 小时前
电商金融贷款服务市场趋势与竞争分析
java·前端·人工智能
百度森森3 小时前
【nuscenes数据集有关】
c++·数码相机·学习·ubuntu