方法住在哪里?堆栈还是堆?

时间:2009-07-30 19:10:40

标签: java jvm stack heap

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

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

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

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

6 个答案:

答案 0 :(得分:8)

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

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

  

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

我见过许多场景,其中客户端已经实现了大量线程化的服务器,因为每个线程都做得很少,并且它们会遇到内存问题。那是因为每个线程都分配了自己的堆栈,这显然加起来了。我认为默认值是每个线程512k,但我没有找到一个规范的来源。

答案 1 :(得分:8)

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

对于(差)ASCII表示:

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

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

这就是我的记忆所说的 - 一些细节可能是错误的。

答案 2 :(得分:6)

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

main(args)

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

method()
main(args)

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

对于带有线程的示例,每个线程都有自己的堆栈,该堆栈独立于彼此的线程堆栈而存在。

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

堆被分成多代。

字节码及其相应的JIT编译机器代码存在于所谓的永久生成中,以及实习字符串和其他类数据。

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

答案 5 :(得分:0)

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