Java虚拟机是否移动内存中的对象,如果是,如何移动?

Java虚拟机是否移动内存中的对象,如果是,如何移动?,java,memory-management,garbage-collection,jvm,Java,Memory Management,Garbage Collection,Jvm,Java虚拟机是否移动过内存中的对象?如果是,它如何处理对移动对象的更新引用 我这样问是因为我正在探索以分布式方式(即跨多个服务器)存储对象的想法,但出于效率原因,我需要能够在服务器之间移动对象。对象需要能够包含指向彼此的指针,甚至指向远程服务器上的对象。我在想更新对移动对象的引用的最佳方法 到目前为止,我的两个想法是: 在对象生命周期内不移动的地方维护一个间接引用,如果对象移动,我们会更新该引用。但是,这些间接行为是如何管理的 为每个对象保留一个反向引用列表,这样我们就知道如果对象被移动,需要

Java虚拟机是否移动过内存中的对象?如果是,它如何处理对移动对象的更新引用

我这样问是因为我正在探索以分布式方式(即跨多个服务器)存储对象的想法,但出于效率原因,我需要能够在服务器之间移动对象。对象需要能够包含指向彼此的指针,甚至指向远程服务器上的对象。我在想更新对移动对象的引用的最佳方法

到目前为止,我的两个想法是:

  • 在对象生命周期内不移动的地方维护一个间接引用,如果对象移动,我们会更新该引用。但是,这些间接行为是如何管理的
  • 为每个对象保留一个反向引用列表,这样我们就知道如果对象被移动,需要更新什么。当然,这会产生性能开销
  • 我对这些方法的反馈以及其他方法的建议很感兴趣。

    (实际上)任何垃圾收集系统都必须在内存中移动对象,以便将它们更密集地打包并避免碎片问题

    你所看到的是一个非常大和复杂的主题。我建议您仔细阅读现有的远程对象样式API:.NET远程处理以及类似的技术

    任何跟踪参考的解决方案都将因为必须处理分布式系统中存在的所有故障模式而变得复杂。JVM不必担心由于网络交换机故障而突然发现无法看到堆的一半

    当你深入研究设计时,我想很多问题都会归结到你想如何处理不同的失败案例

    回复评论:

    您的问题涉及以分布式方式存储对象,这正是.NETRemoting和CORBA所解决的问题。诚然,这两种技术都不支持这些对象的迁移(AFAIK)。但它们都广泛地涉及对象标识的概念,而对象标识是任何分布式对象系统的关键部分:系统的不同部分如何知道它们在谈论哪些对象

    我对Java垃圾收集器的细节不太熟悉,我相信Java和.NET垃圾收集器有很多复杂性,可以在对应用程序影响最小的情况下实现最大性能

    但是,垃圾收集的基本思想是:

    • VM停止所有线程运行托管代码
    • 它从一组已知的“根”执行可达性分析:静态变量、所有线程上的局部变量。对于找到的每个对象,它都遵循对象内的所有引用
    • 任何未通过可达性分析识别的对象都是垃圾
    • 然后,可以在内存中向下移动仍处于活动状态的对象,以便将它们密集地打包。这意味着对这些对象的任何引用也必须用新地址更新。通过控制垃圾回收的发生时间,VM能够保证没有会导致问题的对象引用“在空中”(即保存在机器寄存器中)
    • 进程完成后,VM将再次启动线程执行
    作为此过程的细化,VM可以执行分代垃圾收集,其中根据对象的“年龄”维护单独的堆。对象从堆0开始,如果它们在几个GC中存活下来,则会迁移到堆1,最终迁移到堆2(以此类推-.NET仅支持3代)。这样做的好处是,GC可以非常频繁地运行heap 0集合,并且不必担心如何证明长寿命对象(最终在heap 2中)仍然是活动的(它们几乎肯定是活动的)


    还有其他一些改进来支持并发垃圾回收,以及在调度GC时实际执行非托管代码的线程的详细信息,这给这一领域增加了更多的复杂性。

    您想要的关键字是“压缩垃圾回收器”。JVM被允许使用一个,这意味着可以重新定位对象。请参阅JVM手册,了解您的JVM是否有,并查看是否有任何命令行选项会影响它

    从概念上讲,解释压缩的最简单方法是假设垃圾收集器冻结所有线程,重新定位对象,在堆和堆栈中搜索对该对象的所有引用,并用新地址更新它们。实际上,它比这更复杂,因为出于性能原因,您不希望在线程停止的情况下执行完全扫描,所以增量垃圾收集器将尽可能地为压缩做准备


    如果您对间接引用感兴趣,可以从研究Java中的弱引用和软引用,以及各种RPC系统使用的远程引用开始。

    参考上面关于遍历堆的评论

    不同的GC使用不同的方法

    通常,当收集器遍历堆时,它们不会遍历堆中的所有对象。而是在堆中行走活动对象。这意味着,如果可以从“根”对象访问该对象,则该对象是活动的

    因此,在这个阶段,is必须接触所有活动对象,因为它将它们从旧堆复制到新堆。一旦活动对象的复制完成,旧堆中剩余的所有对象要么是已经复制的对象,要么是垃圾。此时,旧堆可以完全丢弃

    这种收集器的两个主要优点是,它在复制阶段压缩堆,并且只复制活动对象。这对许多系统都很重要,因为使用这种收集器,对象分配非常便宜,实际上只不过是增加一个堆指针。当GC ha