Possible open file leak in com.sun.tools.javac.file.JavacFileManager (original) (raw)

Andreas Fey fey at apiomat.com
Mon Nov 5 14:24:16 UTC 2018


Hi all,

we maybe found a bug in the com.sun.tools.javac.file.JavacFileManager; our tool makes heavy use of compiling classes during runtime, and after switching from JDK 8 to 11, we noticed hundreds of open files being created during list() and only closed when JVM exists. The concerning lines of code are:

@Override @DefinedBy(Api.COMPILER) public Iterable list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException { checkNotModuleOrientedLocation(location); // validatePackageName(packageName); nullCheck(packageName); nullCheck(kinds);

    Iterable<? extends Path> path = getLocationAsPaths(location);
    if (path == null)
        return List.nil();
    RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName);
    ListBuffer<JavaFileObject> results = new ListBuffer<>();

    for (Path directory : path) {
        Container container = getContainer(directory);

        container.list(directory, subdirectory, kinds, recurse, results);
    }

    return results.toList();
}

We think, a container.close() is missing in the for loop. Without this, a filehandle is created for every container/directiry found here. To test this, the following code snipped can be used, but the location must be set property to find a valid path != null:

@Test public void testFileManager( ) throws IOException { countOpenFiles( );

final Set<javax.tools.JavaFileObject.Kind> kinds = new HashSet<>( ); kinds.add( javax.tools.JavaFileObject.Kind.OTHER ); kinds.add( javax.tools.JavaFileObject.Kind.SOURCE ); kinds.add( javax.tools.JavaFileObject.Kind.CLASS ); kinds.add( javax.tools.JavaFileObject.Kind.HTML );

final StandardJavaFileManager sfm = ToolProvider.getSystemJavaCompiler( ).getStandardFileManager( null, null, null ); sfm.list( new JavaFileManager.Location( ) { @Override public boolean isOutputLocation( ) { return false; }

@Override public String getName( ) { return "CLASS_NAME"; } }, "com", kinds, true );

countOpenFiles( ); }

private void countOpenFiles( ) { final String processName = java.lang.management.ManagementFactory.getRuntimeMXBean( ).getName( ); final long pid = Long.parseLong( processName.split( "@" )[ 0 ] ); try { final Runtime rt = Runtime.getRuntime( ); final Process pr = rt.exec( "lsof -p " + pid );

int ctr = 0; final BufferedReader br = new BufferedReader( new InputStreamReader( pr.getInputStream( ) ) ); while ( ( br.readLine( ) ) != null ) ctr++; pr.waitFor( ); pr.destroy( );

System.out.println( "Open files: " + ctr ); } catch ( final Exception e ) { e.printStackTrace( ); } }

Can anybody confirm this? Best, Andreas -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20181105/f40a972c/attachment.html>



More information about the compiler-dev mailing list