Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
终结器线程等待时java.util.ref.Finalizer内存泄漏_Java_Memory_Garbage Collection_Jvm_Finalize - Fatal编程技术网

终结器线程等待时java.util.ref.Finalizer内存泄漏

终结器线程等待时java.util.ref.Finalizer内存泄漏,java,memory,garbage-collection,jvm,finalize,Java,Memory,Garbage Collection,Jvm,Finalize,分析堆转储时,我会查找java.lang.ref.Finalizer类的实例。Finalizer有“next”和“prev”成员字段用于维护链表。我总是将FileInputStream作为列表的尾部,将FileOutputStream作为列表的前一个条目(分析了几个堆转储)。FileInputStream和FileOutputStream的文件描述符始终分别为0和1: +---[Pending Finalization] java.lang.ref.Finalizer |

分析堆转储时,我会查找java.lang.ref.Finalizer类的实例。Finalizer有“next”和“prev”成员字段用于维护链表。我总是将FileInputStream作为列表的尾部,将FileOutputStream作为列表的前一个条目(分析了几个堆转储)。FileInputStream和FileOutputStream的文件描述符始终分别为0和1:

+---[Pending Finalization] java.lang.ref.Finalizer           
| |                                                          
| +---queue  java.lang.ref.ReferenceQueue [Stack Local]      
| |                                                          
| +---referent  java.io.FileInputStream                     
| | |                                                        
| | +---closed = boolean false                               
| | |                                                        
| | +---closeLock  java.lang.Object                          
| | |                                                        
| | +---fd  java.io.FileDescriptor                           
| |   |                                                      
| |   +---closed = boolean false                             
| |   |                                                      
| |   +---fd = int 0                                         
| |   |                                                       
| |   +---parent  java.io.FileInputStream                    
| |                                                          
| +---prev  [Pending Finalization] java.lang.ref.Finalizer   
|   |                                                        
|   +---queue  java.lang.ref.ReferenceQueue [Stack Local]    
|   |                                                        
|   +---next  [Pending Finalization] java.lang.ref.Finalizer 
|   |                                                        
|   +---referent  java.io.FileOutputStream                   
|   | |                                                      
|   | +---append = boolean false                             
|   | |                                                      
|   | +---closed = boolean false                             
|   | |                                                       
|   | +---closeLock  java.lang.Object                        
|   | |                                                     
|   | +---fd  java.io.FileDescriptor                         
|   |   |                                                    
|   |   +---closed = boolean false                           
|   |   |                                                    
|   |   +---fd = int 1  0x00000001                           
|   |   |                                                    
|   |   +---parent  java.io.FileOutputStream                 
|   |                                                         
|   +---prev  [Pending Finalization] java.lang.ref.Finalizer 
  • 为什么FileInputStream和FileOutputStream总是位于引用队列的尾部
  • 它们不是由垃圾收集器收集的吗?因为我观察到只有分配失败GC而不是完全GC发生
  • 为什么它们的描述符总是0和1

  • 也许下面的测试程序会对此有所启发:

    Field fd = FileDescriptor.class.getDeclaredField("fd");
    fd.setAccessible(true);
    System.out.println("stdin:  "+fd.get(FileDescriptor.in));
    System.out.println("stdout: "+fd.get(FileDescriptor.out));
    System.out.println("stderr: "+fd.get(FileDescriptor.err));
    
    stdin:0
    标准:1
    标准:2
    
    ,请注意,对于JDK 8,这仅适用于类Unix系统

    换句话说,您正在查看由
    System.In
    System.out
    封装的文件流,当然,这些文件流永远不会被垃圾收集,通常也不会对它们调用
    close()

    终结不支持任何类型的选择退出,因此具有“非平凡的
    finalize()
    方法”的类的任何实例在构造时都将获得终结器引用,即使创建者知道对象永远不会被终结

    最新的JDK版本为此使用了,这允许在使用现有的
    文件描述符构建
    文件输入流
    文件输出流
    时不注册清洁器,这是stdin和stdout的情况。它还允许立即清理,从而在
    close()
    方法中取消注册,而不需要对行为良好的程序进行任何事后清理


    因此,对于最新的Java版本,您应该只看到堆转储中实际使用的流的清理器。

    您正在泄漏文件输入和输出流。解决方案:不要。@user207421,不幸的是,你的回答看起来不像是对这三个问题的回答。