首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解Java内存管理

了解Java内存管理
EN

Stack Overflow用户
提问于 2012-12-13 15:28:40
回答 10查看 46.7K关注 0票数 17

Java程序员知道JVM运行垃圾回收器,而System.gc()只是建议JVM运行垃圾回收器。如果我们使用System.gc(),它不一定会立即运行GC。

如果我误解了Java的垃圾收集器,请纠正我。

除了依赖Java的垃圾收集器之外,是否还有其他方法来进行内存管理?

如果您打算通过某种编程实践来回答这个问题,这将有助于管理内存,请这样做。

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2012-12-13 15:38:54

关于Java内存管理,需要记住的最重要的事情就是“取消”你的引用。

只有未被引用的对象才会被垃圾回收。

例如,以下代码中的对象永远不会被收集,如果不执行任何操作,您的内存将会满。

代码语言:javascript
复制
List objs = new ArrayList();
for (int i = 0; i  < Integer.MAX_VALUE; i++) objs.add(new Object());

但是如果你不引用这些对象..。你可以随心所欲地循环,不会有内存问题。

代码语言:javascript
复制
List objs = new ArrayList();
for (int i = 0; i  < Integer.MAX_VALUE; i++) new Object();

因此,无论您做什么,都要确保删除对不再使用对象的引用(设置对null的引用或清除集合)。

垃圾收集器何时运行最好留给JVM来决定。除非您的程序将要开始执行使用大量内存且对速度至关重要的工作,否则您可能会建议JVM在进入之前运行GC,因为您可能会获得收集的垃圾和额外的内存。否则,我个人认为没有理由运行System.gc()

希望这能有所帮助。

票数 16
EN

Stack Overflow用户

发布于 2012-12-13 15:36:27

下面是我过去写的一个小摘要(我从一些博客上偷来的,但我不记得是从哪里来的--所以没有参考,抱歉)

  1. There是一种非手动的垃圾收集方式,在Java.
  2. Java中堆被分成三代来进行垃圾收集。新对象是在年轻一代中创建的,随后移动到旧generation.
  3. String池中是在堆的Perm区域中创建的,垃圾收集可以在perm空间中发生,但取决于generation.
  4. Whenever to

  1. 次要垃圾收集用于将对象从伊甸园空间移动到幸存者1和幸存者2空间,而主要垃圾回收用于将对象从年轻对象移动到永久JVM应用程序。线程在此期间停止,这将降低应用程序的性能,throughput.
  2. There很少。在Java6中,垃圾收集应用了性能改进,我们通常使用JRE1.6.20来运行我们的application.
  3. JVM命令行选项,-Xms-Xmx用于设置Java Heap的启动和最大大小。根据我的经验,此参数的理想比例为1:1或1:1.5。例如,您可以将–Xmx–Xms都设置为1 GB,或者将-Xms设置为1.2 GB和1.8 GB。

命令行选项:-Xms:<min size> -Xmx:<max size>

票数 16
EN

Stack Overflow用户

发布于 2012-12-14 05:41:40

补充一下:垃圾收集并不是中内存管理的唯一形式。

过去,在实现内存管理时,人们一直在努力避免在Java语言中使用GC (参见Real-time Specification for Java (RTSJ))。这些工作主要致力于Java中的实时和嵌入式编程,由于性能开销或GC引入的延迟,GC不适合这些编程。

RTSJ特性

  • 不朽和作用域内存管理-请参阅下面的示例。
  • GC和不朽/作用域内存可以与需要特殊修改的
  • 共存。

RTSJ的优势:

能够满足实时系统requirements的低延迟、无GC pauses

  • delivers可预测性能的

为什么RTSJ失败/没有产生很大的影响:

在实时GC中,

  • 作用域内存的概念难以编程、容易出错和难以learn.
  • Advance。通过在大多数实时应用程序中使用实时GC来代替实时GC,减少了GC暂停时间。但是,作用域内存仍然用于不能容忍延迟的地方。

作用域内存代码示例(取自An Example of Scoped Memory Usage):

代码语言:javascript
复制
import javax.realtime.*;
public class ScopedMemoryExample{

    private LTMemory myMem;

    public ScopedMemoryExample(int Size) {

       // initialize memory
       myMem = new LTMemory(1000, 5000); 
    }

public void periodicTask() {

  while (true)) {
    myMem.enter(new Runnable() {
        public void run() {
          // do some work in the SCOPED MEMORY
          new Object();
          ...
          // end of the enter() method, the scoped Memory is emptied.  
        }
    });
  }


}
}

在这里,预先分配了一个名为LTMemory的ScopedMemory实现。然后线程进入作用域内存,分配仅在计算期间需要的临时数据。计算结束后,线程离开作用域内存,这会立即清空特定ScopedMemory的整个内容。没有引入延迟,在恒定的时间内完成,例如可预测的时间,没有触发GC。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13855013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档