编译器书(The Dragon book)解释了在堆栈上创建的值类型,并在堆上创建了引用类型.
对于Java,JVM还在运行时数据区域中包含堆和堆栈.在堆上创建对象和数组,方法帧被推送到堆栈.所有线程共享一个堆,而每个线程都有自己的堆栈.下图显示了这一点:

有关Java运行时数据区的更多信息.
我不明白的是,由于JVM本质上是一个软件,那些JVM堆,堆栈和线程如何映射到物理机器?
如果有人可以比较Java和C++之间的这些概念,我将不胜感激.因为Java在JVM上运行,但C++没有.
为了使这个问题更加准确,我想知道以下内容:
更新:我为进程的运行时物理内存绘制了一张图片.

我在Android应用程序中遇到了一个非常奇怪的问题.在某个点之后(主要活动开始并且显示片段的时候),FinalizerDaemon会停止处理对象并且垃圾堆积不断.看一下线程转储,它似乎停留在ReferenceQueue.remove():
"FinalizerDaemon@4461" daemon prio=5 waiting
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:423)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101)
- locked <0x1173> (a java.lang.ref.ReferenceQueue)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185)
at java.lang.Thread.run(Thread.java:818)
Run Code Online (Sandbox Code Playgroud)
但队列并非空.如果我在使用app一段时间之后转储堆,那么队列实际上是数千个条目.数据结构也看起来不破:

在分配和垃圾收集后再次转储更多显示队列的头部与以前相同的Matrix实例.
现在,我注意到了这一点,因为我保留了一些C++对象,需要在某些时候释放它们.虽然我怀疑终结器调用JNI函数并在C++端做一些愚蠢的操作可能会以某种方式破坏它,但我的所有日志都表明所有终结器都运行良好并返回而不会抛出任何东西,直到它们随机停止被调用.此外,最终的调用不应该打破守护进程,除了整个应用程序或其他东西,因为看门狗应该处理运行时间太长并抛出异常的终结器.
我尝试了一个显式的System.runFinalization(),它所做的只是永远挂起主线程,等待从未运行的守护进程.
知道怎么会这样吗?
例如,你有一个像这样的转储:
"MyThread"prio = 1 tid = 0x0850c9f8 nid = 0x1baf runnable
这里的nid是什么意思?它是pid或lwpid的十六进制值吗?
我正在攻读java考试,在过去的考试中,讲师问了这个问题,我想知道是否有人可以帮助我理解它:
在java解释线程的上下文中.举例说明何时可以使用线程.命名两个java虚拟机线程.
问题的前两部分很容易,但关于命名两个VM线程的部分实际上是让我感到困惑.