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