我知道方法的局部变量和参数存在于堆栈中,但我无法弄清楚Java的实际方法在哪里?
如果我声明任何Thread对象,如:
Thread t=new Thread();
t.start();
所以这意味着除了main方法之外我还创建了一个单独的方法调用。这是什么意思?这是否意味着在堆栈内存上调用单独的方法序列?我是对的吗?
答案 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代码将存在于进程的内存中。在进程内存中可能只有一个副本,因为给定进程中的所有线程共享该内存。这些线程的任何变量共享将由共同的方法访问。线程的局部变量(即使是线程中使用的方法局部变量)也将在该线程的内存中创建。