【问题标题】:Where methods live? Stack or in Heap?方法在哪里?堆栈还是堆中?
【发布时间】:2010-11-15 13:45:52
【问题描述】:

我知道方法的局部变量和参数存在于堆栈中,但我无法弄清楚在 Java 的情况下方法实际存在于哪里?

如果我声明任何 Thread 对象,例如:

Thread t=new Thread();
t.start();

所以这意味着我已经创建了一个单独的方法调用,除了 main 方法。这是什么意思?这是否意味着在堆栈内存上调用单独的方法序列?我说的对吗?

【问题讨论】:

  • 你的措辞让我感到不舒服。代码空间中的“方法”“生活”。它不在堆栈或堆上。在堆上创建一个对象,它的每个方法都有一个指针。该对象位于堆中,但它指向的方法在代码中。

标签: java jvm heap-memory stack-memory


【解决方案1】:

每个线程都分配有自己的堆栈。

This article 很好地介绍了 Java 进程中的内存分离。

在 Java 虚拟机中,每个 线程被授予一个 Java 堆栈,它 包含其他线程无法包含的数据 访问,包括局部变量, 参数和每个的返回值 线程调用的方法。这 堆栈上的数据仅限于 原始类型和对象引用。 在JVM中,不可能 将实际物体的图像放在上面 堆栈。所有对象都驻留在 堆。

我见过很多场景,客户端在每个线程做的很少的基础上实现了大量线程的服务器,并且他们遇到了内存问题。那是因为每个线程都分配了自己的堆栈,并且(显然)加起来了。我认为默认值是每个线程 512k,但我还没有找到它的规范来源。

【讨论】:

    【解决方案2】:

    如果我没记错的话,方法代码本身将存在于内存的代码部分,而内部声明的变量将存在于堆栈中,而对象将在堆上创建。在 Java 中,变量指针和原语存在于堆栈中,而任何创建的对象都存在于堆中。

    对于(较差的)ASCII 表示:

    -------
    |STACK|
    -------
    |FREE |
    -------
    |HEAP |
    -------
    |CODE |
    -------
    

    其中STACK代表栈,FREE代表空闲内存,HEAP代表堆,CODE代表代码空间。

    这是我的记忆——有些细节可能是错误的。

    【讨论】:

    • 正如 Brian Agnew 所指出的,每个进程都有自己的堆栈,而它们共享堆。
    【解决方案3】:

    堆栈由方法调用组成。 java压栈的是一个方法调用记录,它封装了该方法的所有变量(参数和本地实例化的变量)。当您启动 Java 应用程序时,main 方法(自动包含 args 参数)是堆栈上唯一的东西:

    main(args)
    

    当你创建一个 Foo 对象并调用 foo.method() 时,堆栈现在看起来像:

    method()
    main(args)
    

    当方法被调用时,它们被压入堆栈,当它们返回时,它们被从堆栈中移除或“弹出”。随着变量的声明和使用,对应于当前方法(位于堆栈顶部)的堆栈条目会增长到包含变量的大小。

    对于您的线程示例,每个线程都有自己的堆栈,独立于其他线程的堆栈而存在。

    【讨论】:

      【解决方案4】:

      堆栈包含所有局部变量和所有活动方法调用。 堆包含其他所有内容。

      至于您的子问题:这意味着使用自己的专用内存创建了一个新堆栈。 虽然您的新线程将共享 jvm 分配的总堆空间(内存)

      【讨论】:

      • 我很确定堆栈包含所有本地 primitive 变量和指向实际对象的指针(以及真正的引用)。
      【解决方案5】:

      堆被分成多代。

      字节码及其对应的 JIT 编译机器码与内部字符串和其他类数据一起存在于所谓的永久代中。

      即使它被称为“永久”代,它仍然可以被垃圾回收。一些库、框架和 JVM 语言在运行时生成字节码,因此永久代有时需要清理。就像堆的其他几代一样,但(通常希望)不那么频繁。

      【讨论】:

        【解决方案6】:

        实际的字节码和/或 JIT 代码将存在于进程的内存中。进程内存中可能只有一个副本,因为给定进程中的所有线程共享该内存。这些线程共享的任何变量都将被公共方法访问。线程的局部变量(甚至是线程中使用的方法局部变量)将在该线程的内存中创建。

        【讨论】:

          猜你喜欢
          • 2021-05-25
          • 2013-10-26
          • 1970-01-01
          • 2014-08-14
          • 2010-10-26
          • 2013-01-10
          • 2016-09-08
          • 1970-01-01
          • 2010-11-06
          相关资源
          最近更新 更多