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

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

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

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

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

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

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

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

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

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

对于(差)ASCII表示:

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

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

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

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

 main(args) 

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

 method() main(args) 

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

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

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

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

堆被分成多代。

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

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

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