(original) (raw)

Jon,

is there an  
Thanks,

Andreas

On 11/5/18 15:55 AM, Jonathan Gibbons wrote:
> 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 kinds,  
> boolean recurse)  
> throws IOException  
> {  
> checkNotModuleOrientedLocation(location);  
> // validatePackageName(packageName);  
> nullCheck(packageName);  
> nullCheck(kinds);  
>  
> Iterable 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 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