JVM的堆栈、堆和线程如何映射到物理内存或操作系统

57

编译器书(龙书)解释说,值类型在栈上创建,引用类型在堆上创建。

对于Java,JVM在运行时数据区中也包含了堆和栈。对象和数组在堆上创建,方法帧则被推入栈中。一个堆由所有线程共享,而每个线程都有自己的栈。以下图表显示了这一点:

enter image description here

更多关于Java运行时数据区域的内容。

我不理解的是,既然JVM本质上是软件,那么这些JVM堆、栈和线程如何映射到物理机器上呢?

如果有人能比较Java和C++之间的这些概念就好了。因为Java运行在JVM上,而C++则不是。

为了使这个问题更加精确,我想知道以下几点:

  1. 与Java相比,C++的运行时数据区域看起来是什么样子的?图片将会很有帮助,我找不到像上面JVM那张好的图片。
  2. JVM堆、栈、寄存器和线程是如何映射到操作系统的?或者说它们是如何映射到物理机器的?
  3. 每个JVM线程是否只是一个用户线程,并以某种方式映射到内核中?(用户线程与内核线程)

更新:我为进程的运行时物理内存绘制了一张图片。
enter image description here


3
大多数线程只是映射到操作系统线程,此时它们会像操作系统上的任何线程一样拥有自己的堆栈。 - radai
@radai 很好,感谢您的评论!您能否通过比较Java和C ++来说得更多? - Ryan
我对C++不是很了解,无法进行比较,我只熟悉Java。 - radai
1个回答

39

我不明白的是,由于JVM本质上是软件,那么JVM堆、栈和线程是如何映射到物理机器上的?

堆是预分配的虚拟内存连续区域。例如:

 void* heap = malloc(Xmx); // get the maximum size.

当线程启动时,堆栈由线程库分配。再次,它是最大堆栈大小的连续虚拟内存区域。你可以将其看作是

 void* stack = malloc(Xss); // get the maximum stack size.

本地线程是操作系统的功能,不是JVM本身的一部分。

因为Java运行在JVM上,但C++不是。

C++仍然需要运行时环境和库才能启动。尝试删除C++运行时或libc,它们将无法启动。

与Java相比,C++运行时数据区域是什么样子的?

有一个大的虚拟内存区域可供使用。没有图片,因为它并不能告诉你太多信息。想象一个标记为用户空间的长方形。

JVM堆、堆栈、寄存器和线程是如何映射到操作系统的?或者我应该问它们如何映射到物理机器上?

同样没有什么魔法。JVM堆是一块内存区域,JVM堆栈与C++使用的本地堆栈相同,JVM的寄存器与C++使用的原生寄存器相同,JVM的线程实际上是C++使用的本地线程。

我认为您认为存在更多的魔法或模糊性。相反,您应该假设使用了最简单、高效和轻量级的设计,这样您就不会偏离正确方向。

我应该问它们如何映射到物理机器上?

基本上是一对一的。


@alfasin JVM使用的堆栈空间可能不是连续的,单个线程的堆栈空间通常是连续的,因为做其他事情会变得复杂/昂贵。 - Peter Lawrey
@PeterLawrey 你说得对 - 只要实现使用固定大小的堆栈,这就是有意义的。 - Nir Alfasi
@alfasin 在虚拟内存方面,大小是固定的。这意味着您可以拥有一个10 MB的堆栈,但只有访问的页面使用主内存。 - Peter Lawrey
@PeterLawrey 没错,而且当使用VM时,它可能不会是连续的。 - Nir Alfasi
@alfasin 但是由于内存是随机访问的,页面可以位于任何位置,但这并不重要。所有程序看到的都是一个连续的地址空间。 - Peter Lawrey
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接