草庐IT

java - java中的静态分配——堆、栈和永久代

coder 2023-04-27 原文

我最近阅读了很多关于 Java 内存分配方案的文章,在阅读各种来源的文章时,有很多疑问。我已经收集了我的概念,我会要求检查所有要点并对其进行评论。我开始知道内存分配是特定于 JVM 的,所以我必须事先说明,我的问题是特定于 Sun 的。

  • 类(由类加载器加载)位于堆上的一个特殊区域:永久代
  • 所有与类相关的信息,如类名、与类关联的对象数组、JVM 使用的内部对象(如 java/lang/Object)和优化信息都进入永久代区域。
  • 所有的静态成员变量再次保存在永久代区域。
  • 对象在不同的​​堆上:年轻代
  • 每个类的每个方法只有一个副本,无论是静态方法还是非静态方法。该副本被放入永久世代区域。
    对于非静态方法,所有参数和局部变量都进入堆栈 - 每当有该方法的具体调用时,我们都会得到一个与之关联的新堆栈帧。
    我不确定静态方法的局部变量存储在哪里。他们是否在永久代的堆上?或者只是他们的引用存储在永久代区域,而实际副本在其他地方(哪里?)
  • 我也不确定方法的返回类型存储在哪里。
  • 如果对象(在年轻代中)需要使用静态成员(在永久代中),它们会被赋予对静态成员的引用 && 它们被赋予足够的内存空间来存储方法的返回类型等。

  • 谢谢你经历了这一切!

    最佳答案

    首先,您现在应该很清楚,很少有人能够从第一手知识中确认这些答案。很少有人在最近的 HotSpot JVM 上工作或研究它们到真正了解所需的深度。这里的大多数人(包括我自己)都是根据他们在别处看到的东西或他们推断出来的东西来回答的。通常,这里或各种文章和网页中所写的内容是基于其他来源,这些来源可能是确定的,也可能不是。它通常被简化、不准确或完全错误。

    如果您想对您的答案进行明确确认,您确实需要下载 OpenJDK 源代码……并通过阅读和理解源代码来进行自己的研究。就 SO 提出问题,或浏览随机的网络文章并不是一种可靠的学术研究技术。

    话虽如此...

    ... my question is Sun specific.



    在提出这个问题时,Sun Microsystems 已经不复存在。因此,该问题是特定于 Oracle 的。 AFAIK,所有当前(非研究)第 3 方 JVM 实现要么是 OpenJDK 版本的直接端口,要么是另一个 Sun/Oracle 版本的后代。

    下面的答案适用于 Oracle Hotspot 和 OpenJDK 版本,可能也适用于大多数其他版本......包括 GraalVM。

    1) Classes (loaded by the classloaders) go in a special area on heap : Permanent Generation.



    在 Java 8 之前,是的。

    从 Java 8 开始,永久代空间已被元空间取代。加载的和 JIT 编译的类现在去那里。 PermGen 不再存在。

    2) All the information related to a class like name of the class, Object arrays associated with the class, internal objects used by JVM (like java/lang/Object) and optimization information goes into the Permanent Generation area.



    或多或少,是的。我不确定你所说的其中一些是什么意思。我猜测“JVM 使用的内部对象(如 java/lang/Object)”意味着 JVM 内部类描述符。

    3) All the static member variables are kept on the Permanent Generation area again.



    变量本身是的。这些变量(与所有 Java 变量一样)将保存原始值或对象引用。然而,虽然静态成员变量位于在 permgen 堆中分配的框架中,但这些变量引用的对象/数组可以在任何堆中分配。

    4) Objects go on a different heap : Young generation



    不一定。大对象可以直接分配到老年代。

    5) There is only one copy of each method per class, be the method static or non-static. That copy is put in the Permanent Generation area.



    假设您指的是该方法的代码,那么 AFAIK 是的。不过可能会稍微复杂一些。例如,代码可能在 JVM 生命周期的不同时间以字节码和/或 native 代码形式存在。

    ... For non-static methods, all the parameters and local variables go onto the stack - and whenever there is a concrete invocation of that method, we get a new stack-frame associated with it.



    是的。

    ... I am not sure where are the local variables of a static method are stored. Are they on the heap of Permanent Generation ? Or just their reference is stored in the Permanent Generation area, and the actual copy is somewhere else (Where ?)



    不。它们存储在堆栈中,就像非静态方法中的局部变量一样。

    6) I am also unsure where does the return type of a method get stored.



    如果您的意思是(非空)方法调用返回的值,那么它要么在堆栈上返回,要么在机器寄存器中返回。如果它在堆栈上返回,则需要 1 或两个字,具体取决于返回类型。

    7) If the objects (in the young generation) nees to use a static member (in the permanent generation), they are given a reference to the static member && they are given enough memory space to store the return type of the method,etc.



    这是不准确的(或者至少,您没有清楚地表达自己)。

    如果某个方法访问一个静态成员变量,它得到的要么是一个原始值,要么是一个对象 引用 .这可以分配给(现有的)局部变量或参数,分配给(现有的)静态或非静态成员,分配给先前分配的数组的(现有)元素,或者简单地使用和丢弃。
  • 在任何情况下都不需要分配新的存储来保存引用或原始值。
  • 通常,存储对象或数组引用只需要一个字的内存,而原始值通常占用一到两个字,具体取决于硬件架构。
  • 在任何情况下,调用者都不需要分配空间来保存方法返回的某些对象/数组。在 Java 中,对象和数组总是使用传值语义返回……但返回的值是对象或数组引用。


  • 有关更多信息,请参阅以下资源:
  • Class metadata: a user guide
  • What is the difference between PermGen and Metaspace?
  • Java 8: From PermGen to Metaspace
  • About G1 Garbage Collector, Permanent Generation and Metaspace
  • 关于java - java中的静态分配——堆、栈和永久代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3849634/

    有关java - java中的静态分配——堆、栈和永久代的更多相关文章

    1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    2. ruby - 其他文件中的 Rake 任务 - 2

      我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

    3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

      作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

    4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

      Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

    5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

      我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

    6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

      我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

    7. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

      刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

    8. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

      通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

    9. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

      我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

    10. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

      我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

    随机推荐