总览

Java 内存区域

先上图

image.png 接下来一块一块来讲

一、c++ 中没有的部分

本地方法栈

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

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

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

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

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

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

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

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

程序计数器PC

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

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

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

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

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

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

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

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

image.png 我们依次看下这些数据在 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 对齐等优化

自动主要是容错

  • 手动的话不释放会有内存泄露
  • 对象量很多的话,显式调用太麻烦,很容易出错、遗漏
  • 缓冲区溢出:手动操作越界等等
本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]