Possible open file leak in com.sun.tools.javac.file.JavacFileManager

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<JavaFileObject> 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