【问题标题】:Java finalize method ,SocksSocketImpl, Profiling and othersJava finalize 方法、SocksSocketImpl、Profiling 等
【发布时间】:2015-03-13 18:08:59
【问题描述】:

我们有一个批处理作业,它从数据库中读取数据并将其写入文件。该作业是在 Spring Batch 2.8 之上编写的。我们注意到,它占用了大量内存并正在尝试对其进行调整。我在练习时有一些问题

  1. 我知道不建议实施 finalize()。在我读过的许多帖子中 - 他们说对象可能被推送到 ReferenceQueue 并且 Finalizer 线程轮询队列。那么有没有办法,我可以自己检查队列? (我知道内存转储会显示这一点,但有时文件太大而无法从实时系统传输到本地计算机并执行诊断)。

  2. 平凡的和不平凡的 finalize() 方法之间究竟有什么区别?找不到解释这一点的文章。

  3. 如果finalize()方法不是个好主意,为什么AbstractPlainSocketImpl、FileInputStream等都实现了?那是怎么回事,他们的 finalize 方法在 GC 中帮助他们而不是成为无法访问或死代码的一部分?

  4. 使用 jvisualvm 或 jmc 时,提交的堆大小显示为 600MB。但是当我在我们的 Linux 环境中执行以下命令时,它显示内存为 800MB+。

    ps --cols 500 -C java -o user,ppid,pid,pcpu,rss,size,vsize,cmd | grep <uid> | awk '{ print $3,$4,$5/1024}'
    

环境细节

    Number of cores: 2
    OS: Red Hat Enterprise Linux Server release 6.5
    Total Physical Memory: 7.69GB
    JVM: Java HotSpot(TM) 64-Bit Server VM (24.45-b08) for linux-amd64 JRE (1.7.0_45-b18)
    JVM Command Line Arguments: -Xloggc:../logs/Job-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:-PrintTenuringDistribution -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=5M -XX:-CITime -XX:-PrintClassHistogram -XX:-PrintConcurrentLocks -XX:-PrintAdaptiveSizePolicy -XX:-TraceClassLoading -XX:-TraceClassUnloading -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=7091 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=server.com

    Garbage Collector used (this info is from JMC): ParallelScavenge for Young and ParallelOld for Old.

【问题讨论】:

  • 平凡和不平凡的 finalize() 方法之间到底有什么区别?找不到解释这一点的文章。 - 区别在于 trivial 终结器,java.lang.ref.Finalizer 的新实例不会为每个实例(具有 trivial 终结器)。如果一个类定义了一个 non-trivial finalize 方法,那么对于该类的每个实例,都会创建一个由 java.lang.Finalizer 类直接引用的 java.lang.ref.Finalizer 实例(保持 Finalizer 的实例活)。见this
  • 就第 3 点而言,finalze() 实现 FileInputStreamAbstractPlainSocketImpl 只是备份调用,用于清理/关闭打开的资源,以防用户无法执行此操作。请注意,finalize() 可能永远不会被调用。该代码的存在是为了确保底层流的关闭,这样您就不会出现任何死锁/阻塞。
  • @TheLostMind 感谢您指向文章。我对 Finalizer 有了更好的了解。

标签: java linux memory-leaks garbage-collection finalizer


【解决方案1】:

我知道内存转储会显示这一点,但有时文件太大而无法从实时系统传输到本地计算机并执行诊断

命令tar -czf dump.tar.gz dump.hprof 可以帮助您传输那个大文件。

3GB -> 100MB。

转储文件的压缩率非常好。

【讨论】:

    猜你喜欢
    • 2014-03-10
    • 2011-06-05
    • 2011-03-19
    • 2013-09-20
    • 2011-08-17
    • 2011-07-07
    • 2016-06-10
    • 2018-12-03
    • 1970-01-01
    相关资源
    最近更新 更多