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

Jonathan Gibbons jonathan.gibbons at oracle.com
Mon Nov 5 15:55:08 UTC 2018


Andreas,

We'll take a look.

-- Jon

On 11/5/18 6:24 AM, Andreas Fey wrote:

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 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 "CLASSNAME"; } }, "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



More information about the compiler-dev mailing list