了解Java的内存管理(Understanding Java Memory Management)

2019-07-05 03:52发布

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

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

是/是有/ s的做不是依赖于Java的垃圾回收器等存储管理的任何其他方式?
如果你打算回答某种编程实践,将有助于管理内存的问题,请这样做。

Answer 1:

最重要的是要记住的Java的内存管理是“抵消”你的参考。

只有不被引用的对象被垃圾回收。

例如,在下面的代码对象是永远不会收集你的记忆将满只是什么都不做。

List objs = new ArrayList();
for (int i = 0; i  < Integer.MAX_VALUE; i++) objs.add(new Object());

但是,如果不引用这些对象......你可以循环,只要你喜欢不带内存的问题一样多。

List objs = new ArrayList();
for (int i = 0; i  < Integer.MAX_VALUE; i++) new Object();

所以,你做什么都,一定要删除参考反对不再使用(设置参考null或明确集合)。

当垃圾收集器将运行最好留给JVM来决定。 好吧,除非你的程序即将开始做的是使用大量内存的东西,是速度的关键,所以你可以建议JVM之前要在你可能会得到garbaged收集额外的内存去运行GC。 其他方面,我个人认为没有理由运行System.gc()

希望这有助于。



Answer 2:

下面是小小的总结我在以后的日子回信(我偷了一些博客,但我不记得从哪里 - 所以没有参考,抱歉)

  1. 现在没有在java做垃圾回收的无手动的方式。
  2. Java堆分为三代垃圾收集的缘故。 这些都是年轻一代,年老或老一代,和彼尔姆地区。
  3. 新对象在年轻一代创建并随后移动到老一代。
  4. 串池堆在彼尔姆地区创建的,可以发生在烫发空间垃圾收集但在JVM依赖于JVM的。
  5. 次要垃圾收集用于从伊甸空间中的对象移动到幸存者1和2幸存者空间,主要集合用于一个对象移动从年轻到年老代。
  6. 每当重大垃圾回收时应用,线程在此期间,这将降低应用程序的性能和吞吐量停止。
  7. 很少有性能方面的改进已经垃圾收集在Java 6的应用和我们平时使用的JRE 1.6.20运行我们的应用程序。
  8. JVM命令行选项-Xms-Xmx用于设置起点和最大尺寸为Java堆。 此参数的理想比例是1:1或1:1.5根据我的经验,例如,你可以有两种–Xmx–Xms为1GB或-Xms 1.2 GB和1.8 GB。

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



Answer 3:

我想补充的讨论: 垃圾收集是不是在Java的内存管理的唯一形式

在过去,一直在努力避免在Java中GC执行内存管理(见时为Java(RTSJ)实时规范 )。 这些努力主要致力于实时Java中的其中GC是不适合嵌入式编程 - 由于性能开销或GC-引入的等待时间。

在RTSJ特点

  • 不朽和作用域内存管理 - 见下面的例子。
  • GC和不朽/作用域内存可以共存withing一个应用程序
  • RTSJ需要经过特别改装的JVM。

RTSJ优势:

  • 低延迟,无GC暂停
  • 提供可预测的性能,能够满足实时系统的要求

为什么RTSJ失败/没有作出大的影响:

  • 区域性存储器概念是很难用编程,容易出错,而且难学。
  • 在实时GC algoritms提前降低GC暂停时以这样的方式,实时更换的GC在大多数实时应用程序的RTSJ。 然而,作用域回忆在没有延迟容忍地方仍在使用。

区域性存储器代码示例(从采取区域性存储器用法的一个示例 ):

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.  
        }
    });
  }


}
}

在这里,一个叫ScopedMemory实现LTMemory预先分配。 然后一个线程进入区域性存储器,分配被仅在计算的时间所需的临时数据。 计算结束后,线程离开区域性存储器并立即作出具体ScopedMemory的全部内容被清空。 无延迟推出,在固定时间如可预见的时间内完成,没有GC被触发。



Answer 4:

从我的经验,在Java中你应该依靠由JVM本身所提供的内存管理。

我会关注这个主题的重点是进行配置的方式为您的使用情况下可以接受的。 也许检查/理解JVM调整选项将是有益的: http://docs.oracle.com/cd/E15523_01/web.1111/e13814/jvm_tuning.htm



Answer 5:

如果你使用Java你无法避免垃圾收集。 也许有一些模糊的JVM实现,这样做,但我不知道有什么。

经过适当调整JVM不应该要求任何System.gc()的提示,以平稳运行。 你需要精确的调整在很大程度上取决于你的应用程序做什么,但我的经验,我总是打开用下列标志并发标记和清除选项: -XX:+UseConcMarkSweepGC 。 此标志允许JVM利用额外的核心,您的CPU清理死内存在后台线程英寸 它有助于大幅减少的时间做垃圾回收时,你的程序被强制暂停的量。



Answer 6:

那么,GC总是存在的 - 你不能创建出它的外面的把握(除非你使用本地调用或分配一个直接字节缓冲区对象,但在后一种情况下,你真的没有对象,只是一堆字节)。 这就是说,它是绝对有可能被重用对象来规避GC。 举例来说,如果你需要一堆ArrayList对象,你可以只创建每一个你需要它,让GC手柄内存管理; 或者你可以拨打list.clear()在每一个你与它完成后,把它放到一些队列哪里别人可以使用它。

标准的最佳做法是,除非你有很好的理由不要做那种重复使用(即,你已经成型并看到分配+ GC是一个问题,那重用对象解决了问题)。 它会导致更复杂的代码,如果你把它错了,它实际上可以使GC的工作更难(因为GC如何跟踪对象)。



Answer 7:

基本上在Java中的想法是,你不应该存储处理,除了使用“新”来分配新的对象,并确保没有留下对对象的引用,当你与他们进行。

其余全是故意留下来的Java运行时,是 - 还特意 - 定义含糊地允许JVM设计师在如此高效做得最自由。

要使用一个比喻:你的操作系统管理命名的硬盘空间区域(称“文件”),为您服务。 包括删除和重用方面你不希望使用任何更多。 你不规避机制,但它留给操作系统

你应该专注于字迹清晰,简单的代码,并确保你的对象是正确地完成。 这将给JVM最好的工作条件。



Answer 8:

你是在说正确System.gc()是编译器的请求,而不是一个命令。 但是,使用下面的程序,你可以确保它发生。

import java.lang.ref.WeakReference;

public class GCRun {

    public static void main(String[] args) {

        String str = new String("TEMP");
        WeakReference<String> wr = new WeakReference<String>(str);
        str = null;
        String temp = wr.get();
        System.out.println("temp -- " + temp);
        while(wr.get() != null) {
            System.gc();
        }
    }
}


Answer 9:

我建议看看下面的教程和它的内容

这是一个四个部分的系列教程了解在垃圾收集的基础知识Java

  1. Java的垃圾回收简介

  2. Java垃圾收集如何运作?

  3. Java垃圾收集器的类型

  4. 监控和分析Java的垃圾回收

我发现本教程非常有帮助。



Answer 10:

“废掉”荷兰国际集团在不需要时参考是使对象符合垃圾回收的最佳方式。

有在其中一个对象可以被垃圾收集4种方式。 1.将引用设置为null,一旦不再需要。

String s = new String("Java");

一旦不需要此字符串,可以点为null。

s = null;

因此,S将有资格进行垃圾回收。

  1. 指向一个对象到另一个,从而使两个参考点到相同的对象和所述对象的一个​​可享有GC。

    字符串S1 =新字符串( “Java” 的);

    字符串s2 =新字符串( “C ++”);

在未来,如果S2还需要指出,S1即可;

s1 = s2;

那么对象具有的“Java”将有资格获得GC。

  1. 在方法中创建的所有对象都符合GC一旦方法完成。 因此,一旦方法被从线程的堆栈被破坏然后该方法中的相应的对象将被破坏。

  2. 隔离的岛是另外一个概念,其中具有内部链接的对象和没有外在链接引用是符合垃圾回收。 垃圾收集的“隔离岛”

例子:下面是Camera类的android系统中的方法。 怎么看开发商指出mCameraSource一旦不需要空。 这是专家级的代码。

public void release() {
        if (mCameraSource != null) {
            mCameraSource.release();
            mCameraSource = null;
        }
    }

垃圾收集器是如何工作的?
垃圾收集被称为垃圾收集器的守护线程执行。 当有足够的可用内存那个时候这个恶魔线程具有较低的优先级且在后台运行。 但是,当JVM发现堆已满,JVM要回收一些内存,然后它会增加垃圾收集器线程的优先级,并要求其搜索所有这些没有引用或空引用和对象Runtime.getRuntime.gc()方法销毁这些对象。



文章来源: Understanding Java Memory Management