在一些关于静态像this和this的文章和教程中,有人说使用静态有利于内存管理,因为静态变量在课堂上只在类区域获取一次内存负荷。
但我的朋友告诉我静态方法保存在堆栈中,因为管理堆比堆栈更容易,垃圾回收器只能在堆上工作,只要应用程序运行,堆栈就不会被清理,尝试使用静态方法尽可能少。
注:
我已经在stackoverflow中读到了关于堆栈内存的相同问题,但我没有得到太多,因为它们是一些复杂和专业的使用" PermGen space"和其他我不知道的词。
我希望有人简单地解释我朋友的进步是否正确?
我知道这取决于,想象一下,我可以使用静态或非静态方法进行设计。记忆管理说哪一个会更好?
答案 0 :(得分:5)
答案是:问这个问题意味着你把时间和精力都花在了错误的地方。
获得性能良好的Java应用程序的关键角色:提出优雅的OOP设计,以直接的方式实现您的需求。
您必须了解" Java性能魔术" Just-in-Time编译器的工作几乎完全发生在运行时。 JIT最擅长于我们所关注的常用模式"最佳实践"在Java中。
试图提出"特别"像"这样的想法让我们可以在整个地方使用静电"甚至可能导致最差的表现 - 因为你的特殊"代码阻止JIT以最佳方式完成其工作。
所以:分别信任JIT的GC。并确保这些工具可以在最佳状态下工作。这样做...别人在做什么!
不要让这种过早优化的想法破坏你的OOP设计。即使您的应用程序属于需要密集低级优化的罕见类别 - 那么您只有一种方法:研究GC和JIT 的深度工作。
换句话说:这些问题不是真正的问题。含义:
然后 - 当你遇到一个真实的"问题:然后您必须配置文件您的应用程序才能了解问题的根本原因。再说一遍:你不允许这种过早(未受过教育)的优化思想以负面的方式影响你的设计。
正如评论暗示我不够清楚:当你有真正的记忆问题时,你绝对必须理解像#34; perm generation" 。因为那时你必须在细节中理解GC的工作原理。说真的:相信这里的人告诉你静态关键字在创建内存效率方面没有任何重要作用。应用
答案 1 :(得分:3)
简短的回答是你的朋友是错的。
class
个对象本身(即java.lang.Class<T>
的实例未在堆栈上分配。
Java在加载类时加载类,并且在加载它们的函数结束时不卸载它们,因此无法进入堆栈。此外,所有线程都访问相同的类对象,但每个线程都有自己的堆栈空间。
警告:本答案的其余部分讨论了JVM实现细节和垃圾收集内存管理。大多数应用程序不需要考虑这些事实,并且不能依赖它们来保证程序的正确性,因为它们可以并且在发布之间进行更改。
许多现代JVM使用世代垃圾收集器,并且因为系统加载的类不会被卸载,所以可以将它们放在称为“永久生成”(PermGen)的区域中,该区域在Java 8中被Oracle替换为MetaSpace。保存问题所指的类元数据。但要认识到这些是Oracle JVM的实现细节,而不是Java规范的一部分。
另一个可能的混淆是,这一切都适用于类直接所需的空间,它是静态引用,但不适用于那些引用引用的内容。
class Sample {
private static BigThing biggie=new BigThing(10000);
}
在示例中,将在堆上创建对象biggie
引用,就像其他任何内容一样。实际上它在这里没有声明final
并且可以引用在执行中的任何点创建的任何对象,因为它可以被重新分配。
这是一篇关于这个主题的最新文章:
https://blogs.oracle.com/poonam/about-g1-garbage-collector,-permanent-generation-and-metaspace
请注意,JVM的这个区域多年来一直在变化和调整,但(据我所知)在Java 9中保持不变。
答案 2 :(得分:2)
静态变量的内存分配仅在程序第一次运行时发生一次。 如果您在类中使用它,则只创建一个由该类的每个对象共享的实例。 所以内存消耗较少。在java8之前,静态方法和变量存储在PERMGEN空间中。但是现在他们引入了名为METASPACE的新内存空间,现在这里是存储所有类方法,类和常量池的字段的地方。 有关METASPACE的更多详细信息,请访问:“https://dzone.com/articles/java-8-permgen-metaspace”