Java File handles won't close

7.9k views Asked by At

Yes this question has been asked before however the issue is a little more complex it seems. I have used all solutions from previous questions that relate to this.

Relates to: Freeing Java File Handles , Java keeps file locks no matter what

package me.test;

import java.io.File;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class Test {
    Logger log = Logger.getAnonymousLogger();
    FileHandler handle;

    final static String newline = System.lineSeparator();
    /**
     * @param args
     */
    public static void main(String[] args) {
        Test t = new Test();
        t.run();
    }
    public void run()
    {
        for (int i = 0; i < 6; i++) {
            testLogs();
            change();
        }
        testLogs();
        if (handle != null)
        {
            handle.close();
            log.removeHandler(handle);
        }
    }
    public static FileHandler craftFileHandler(File file, boolean append)
    {
        if (file == null)
            return null;
        FileHandler fh = null;
        try {
            fh = new FileHandler(file.getPath(), append);
            fh.setFormatter(new Formatter() {

                @Override
                public String format(LogRecord record) {
                    return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline;
                }
            });
            return new FileHandler(file.getPath(), append);
        } catch (Exception e) {
            if (fh != null)
                fh.close();
            return null;
        } 
    }

    public void change()
    {
        if (handle != null)
        {
            handle.flush();
            handle.close();
            log.removeHandler(handle);
        }
        handle = null;
        File f = new File("log.log");
        handle = craftFileHandler(f, true);
        System.out.println(f.getAbsolutePath());
        if (handle != null)
            log.addHandler(handle);
    }
    public void testLogs()
    {
        if (log == null)
        {
            log = Logger.getLogger("test");
            log.setLevel(Level.ALL);
        }
        log.info("This is info #1");
        log.warning("Warning 1");
        log.info("meh info again.");
        log.severe("SEVERE HELL YA NICE TEST");
        log.info("You sure its good here?");
        log.info("Handler count " + log.getHandlers().length);
    }
}

This code is meant to be a test code. I made this test file so I can figure out how to fix this issue on a project I have.

The reason I have a loop of this is because the issue occurs too fast to explain. So a loop was the best way to simulate it. In my project there is a config for a Log file to choose where to put it. But if the file is not changed in config on its reload. It tends to leave the file locked and create extra files EVERY reload

I would like to get this working. If this starts working properly. Then I can properly implement it on my project.

4

There are 4 answers

1
ricochet1k On BEST ANSWER

You are getting multiple files created because you are creating a FileHandler and never closing it.

fh = new FileHandler(file.getPath(), append);
...
return new FileHandler(file.getPath(), append);

The fix?

return fh;

Finally or not makes absolutely no difference. In this case, you actually do want to be closing in the catch block since nothing will be able to close it if you don't.

0
Alexandre On

After use the log method close all handlers.

    this.logger.log(Level.SEVERE, (exception.getClass().getName() + ": " + exception.getMessage()) + "\r\n" + exception.getCause() + "\r\n" + "\r\n");

    for (Handler handler : this.logger.getHandlers())
    {
        handler.close();
    }
1
BlackHatSamurai On

Well, one issue is here:

 try {
            fh = new FileHandler(file.getPath(), append);
            fh.setFormatter(new Formatter() {

                @Override
                public String format(LogRecord record) {
                    return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline;
                }
            });
            return new FileHandler(file.getPath(), append);
        } catch (Exception e) {
            if (fh != null)
                fh.close();
            return null;

You never close the file in the try statement, only closing it if there is an error. You should close the file as soon as you done with it:

 try {
            fh = new FileHandler(file.getPath(), append);
            fh.setFormatter(new Formatter() {

                @Override
                public String format(LogRecord record) {
                    return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline;
                }
            });
            //close fh
            fh.close();
            return new FileHandler(file.getPath(), append);
        } catch (Exception e) {
            if (fh != null)
                fh.close();
            return null;
6
Saj On

Always close resources inside finally block-

try {
    fh = new FileHandler(file.getPath(), append);
    fh.setFormatter(new Formatter() {

    @Override
    public String format(LogRecord record) {
        return "[test] " + "[" + record.getLevel().toString() + "]" + String.format(record.getMessage(), record.getParameters()) + newline;
    }
    });
    return new FileHandler(file.getPath(), append);
} catch (Exception e) {

    return null;
    // never close in catch

} finally {
    //  lastly close anything that may be open
    if (fh != null){
        try {
            fh.close();
        } catch (Exception ex){
            // error closing   
        }
    }
}