从Java调用Ant脚本时如何查找资源泄漏

从Java调用Ant脚本时如何查找资源泄漏,java,debugging,file-io,ant,resource-leak,Java,Debugging,File Io,Ant,Resource Leak,[注意:我发现了资源泄漏(见下面的答案),但我仍然很好奇为什么命令行ant会终止,而java ant却没有终止] 我正在从Java程序中调用一个复杂的ant目标。它运行时没有错误。但最终该计划并未终止。我通过maven execute从NetBeans调用该程序 如果我从命令行调用ant目标,它确实会终止。如果我写入System.exit(0)在我的程序结束时,它终止 因此,我假设要么我错过了一些对ant库的调用,该调用告诉它关闭所有流等等,要么我的ant脚本中存在资源泄漏。我认为这是一个资源泄

[注意:我发现了资源泄漏(见下面的答案),但我仍然很好奇为什么命令行ant会终止,而java ant却没有终止]

我正在从Java程序中调用一个复杂的ant目标。它运行时没有错误。但最终该计划并未终止。我通过maven execute从NetBeans调用该程序

如果我从命令行调用ant目标,它确实会终止。如果我写入
System.exit(0)在我的程序结束时,它终止

因此,我假设要么我错过了一些对ant库的调用,该调用告诉它关闭所有流等等,要么我的ant脚本中存在资源泄漏。我认为这是一个资源泄漏,因为
jstack
报告了一个开放的流(见下文)——我如何才能找出那里有什么开放的

这是我给ant的电话:

public boolean callToAnt() {
File antFile = new File("C:\somepath\build.xml");
File logfile = new File("C:\somepath\antlog.log");
File projectBasePath = antFile.getParentFile();
try (PrintStream logfilestream = new PrintStream(new FileOutputStream(logfile))) {
        Project project = new Project();
        project.setUserProperty("ant.file", antFile.getAbsolutePath());
        project.init();
        ProjectHelper helper = ProjectHelper.getProjectHelper();
        ProjectHelper.configureProject(project, antFile);
        project.setBaseDir(projectBasePath);
        project.addReference("ant.projectHelper", helper);
        project.setProperty("foo", "bar"); // some properties
        project.addBuildListener(getDefaultLogger(logfilestream));
        project.executeTarget("myTarget");
        return true;
    } catch (Exception ex) {
        Logger.getLogger(this.class.getName()).log(Level.SEVERE, null, ex);
        return false;
    }
}
}
我尝试调用
project.fireBuildFinished(null)但这并没有改变任何事情

如果我注释掉ant部分,程序将终止。如果我离开记录器,它仍然不会终止

我不考虑ant脚本本身,因为它分布在许多文件中,非常复杂。我在这里的目标是学习如何自己找到资源泄漏,而不仅仅是解决这个问题

日志文件也不包含任何错误(以“BUILD SUCCESSFUL”结尾)

当进程停止时,我调用了
jstack
,结果如下:

2015-03-23 09:51:40
Full thread dump Java HotSpot(TM) Client VM (25.25-b02 mixed mode):

"Thread-1" #10 daemon prio=5 os_prio=0 tid=0x15b14400 nid=0x120c waiting on condition [0x152ff000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at org.apache.commons.exec.InputStreamPumper.run(InputStreamPumper.java:69)
        at java.lang.Thread.run(Thread.java:745)

"Thread-3" #12 daemon prio=5 os_prio=0 tid=0x15bb9000 nid=0x15b4 runnable [0x164af000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileInputStream.readBytes(Native Method)
        at java.io.FileInputStream.read(FileInputStream.java:224)
        at org.apache.commons.exec.StreamPumper.run(StreamPumper.java:105)
        at java.lang.Thread.run(Thread.java:745)

"Thread-2" #11 daemon prio=5 os_prio=0 tid=0x15bb4000 nid=0x10fc runnable [0x1506f000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileInputStream.readBytes(Native Method)
        at java.io.FileInputStream.read(FileInputStream.java:246)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
        - locked <0x049b25b8> (a java.io.BufferedInputStream)
        at java.io.FilterInputStream.read(FilterInputStream.java:107)
        at org.apache.commons.exec.StreamPumper.run(StreamPumper.java:105)
        at java.lang.Thread.run(Thread.java:745)

"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x14cbb000 nid=0x17f4 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x14caa000 nid=0xcf4 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x14ca9000 nid=0x16c8 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x14ca6000 nid=0x13fc runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0081f000 nid=0x1324 in Object.wait() [0x14ebf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x09bfc108> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
        - locked <0x09bfc108> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:158)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0081a000 nid=0xca0 in Object.wait() [0x14c1f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x09bfc2a8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
        - locked <0x09bfc2a8> (a java.lang.ref.Reference$Lock)

"main" #1 prio=5 os_prio=0 tid=0x000acc00 nid=0x12f4 runnable [0x0221e000]
   java.lang.Thread.State: RUNNABLE
        at java.lang.ProcessImpl.waitForInterruptibly(Native Method)
        at java.lang.ProcessImpl.waitFor(ProcessImpl.java:449)
        at org.apache.commons.exec.DefaultExecutor.executeInternal(DefaultExecutor.java:347)
        at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:160)
        at org.codehaus.mojo.exec.ExecMojo.executeCommandLine(ExecMojo.java:610)
        at org.codehaus.mojo.exec.ExecMojo.execute(ExecMojo.java:352)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)

"VM Thread" os_prio=2 tid=0x00815800 nid=0xa44 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x14cc4c00 nid=0x9b4 waiting on condition

JNI global references: 38
2015-03-2309:51:40
全线程转储Java热点(TM)客户端VM(25.25-b02混合模式):
“线程-1”#10守护进程优先级=5 os#u优先级=0 tid=0x15b14400 nid=0x120c等待条件[0x152ff000]
java.lang.Thread.State:定时等待(休眠)
位于java.lang.Thread.sleep(本机方法)
位于org.apache.commons.exec.InputStreamPumper.run(InputStreamPumper.java:69)
运行(Thread.java:745)
“线程3”#12守护进程优先级=5 os#u优先级=0 tid=0x15bb9000 nid=0x15b4可运行[0x164af000]
java.lang.Thread.State:可运行
位于java.io.FileInputStream.readBytes(本机方法)
在java.io.FileInputStream.read(FileInputStream.java:224)处
位于org.apache.commons.exec.StreamPumper.run(StreamPumper.java:105)
运行(Thread.java:745)
“线程2”#11守护进程优先级=5 os#u优先级=0 tid=0x15bb4000 nid=0x10fc可运行[0x1506f000]
java.lang.Thread.State:可运行
位于java.io.FileInputStream.readBytes(本机方法)
在java.io.FileInputStream.read(FileInputStream.java:246)处
在java.io.BufferedInputStream.fill处(BufferedInputStream.java:246)
位于java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
在java.io.BufferedInputStream.read处(BufferedInputStream.java:345)
-锁定(java.io.BufferedInputStream)
在java.io.FilterInputStream.read(FilterInputStream.java:107)中
位于org.apache.commons.exec.StreamPumper.run(StreamPumper.java:105)
运行(Thread.java:745)
“服务线程”#7守护进程优先级=9 os_优先级=0 tid=0x14cbb000 nid=0x17f4可运行[0x00000000]
java.lang.Thread.State:可运行
“C1编译器线程0”#6守护进程prio=9 os_prio=2 tid=0x14caa000 nid=0xcf4等待条件[0x00000000]
java.lang.Thread.State:可运行
“附加侦听器”#5守护进程优先级=5 os_优先级=2 tid=0x14ca9000 nid=0x16c8等待条件[0x00000000]
java.lang.Thread.State:可运行
“信号分配器”#4守护进程优先级=9 os_优先级=2 tid=0x14ca6000 nid=0x13fc可运行[0x00000000]
java.lang.Thread.State:可运行
对象中的“终结器”#3守护进程优先级=8 os_优先级=1 tid=0x0081f000 nid=0x1324。等待()[0x14ebf000]
java.lang.Thread.State:正在等待(在对象监视器上)
在java.lang.Object.wait(本机方法)
-等待(java.lang.ref.ReferenceQueue$Lock)
位于java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
-锁定(java.lang.ref.ReferenceQueue$Lock)
位于java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:158)
位于java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
对象中的“引用处理程序”#2守护程序prio=10 os_prio=2 tid=0x0081a000 nid=0xca0。wait()[0x14c1f000]
java.lang.Thread.State:正在等待(在对象监视器上)
在java.lang.Object.wait(本机方法)
-等待(java.lang.ref.Reference$Lock)
在java.lang.Object.wait(Object.java:502)
在java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
-锁定(一个java.lang.ref.Reference$Lock)
“main”#1优先级=5操作系统优先级=0 tid=0x000acc00 nid=0x12f4可运行[0x0221e000]
java.lang.Thread.State:可运行
在java.lang.ProcessImpl.waitForInterruptibly处(本机方法)
位于java.lang.ProcessImpl.waitFor(ProcessImpl.java:449)
位于org.apache.commons.exec.DefaultExecutor.executeInternal(DefaultExecutor.java:347)
位于org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:160)
位于org.codehaus.mojo.exec.ExecMojo.executeCommandLine(ExecMojo.java:610)
位于org.codehaus.mojo.exec.ExecMojo.execute(ExecMojo.java:352)
位于org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
位于org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
位于org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
位于org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
位于org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
位于org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
位于org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
位于org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
在org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
在org.a