I expected to find XMLStreamReader to be AutoCloseable in Java 7. However, that is not the case. Is there a technical reason why StAX reader/writer interfaces were not (or should not be) retrofitted to implement AutoCloseable ? They already have close methods, whose intent is not different from the close method of AutoCloseable.
If you look closer to the close() method of AutoCloseable :
Closes this resource, relinquishing any underlying resources. This method is invoked automatically on objects managed by the try-with-resources statement.
Or even Closeable close() method :
Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
Whereas the close() method of XMLStreamReader says :
Frees any resources associated with this Reader. This method does not close the underlying input source.
Indeed the input source is managed by the Reader which implement the Closeable interface. So it's the reader that can be close in the try-with-ressource.
For example :
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = null;
try (FileReader fr = new FileReader("file.xml")) { //Will close the FileReader
reader = factory.createXMLStreamReader(fr);
reader.close();
}
catch (XMLStreamException ex) {
if(reader!=null)try {
reader.close();
} catch (XMLStreamException ex1) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex1);
}
}
There is no technical reason why they couldn't have made these things AutoCloseable. I figure it just comes down to laziness or insufficient time looking for methods called close().
Related
I saw this example, and I didn't see the close() method invoked on the InputStream, so would prop.load() close the stream automatically? Or is there a bug in the example?
The Stream is not closed after Properties.load ()
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(new File("abc.properties"));
new Properties().load(in);
System.out.println(in.read());
}
The above code returns "-1" so the stream is not closed. Otherwise it should have thrown java.io.IOException: Stream Closed
Why do you ask when the javadoc of Properties.load(InputStream inStream) says this?
The specified stream remains open after this method returns.
It has been saying that since Java 6.
As EJP said in a comment: Don't rely on arbitrary Internet junk. Use the official Oracle Java documentation as your primary source of information.
The following try-with-resources will close the InputStream automatically (you can add catch and finally if needed):
try (InputStream is = new FileInputStream("properties.txt")) {
// is will be closed automatically
}
Any resource declared within a try block opening will be closed. Hence, the new construct shields you from having to pair try blocks with corresponding finally blocks that are dedicated to proper resource management.
Article by Oracle here: http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html.
Will try-with-resources call flush() implicitly?
If it does, in the following code snippet, bw.flush() can be safely removed?
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
bw.flush();
} catch (IOException ex) {
// handle ex
}
}
ps.
I don't see any description about it in official document:
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
Closeable and AutoCloseable are general-purpose interfaces that do not know anything about flushing. So you can't find any information about it in their documentation - except some words about releasing resources.
A Writer on the other hand is a more specific-purpose abstract class that now knows something about flushing. Some excerpt of the documentation for the method Writer.close():
Closes the stream, flushing it first.
So - yes - when using a writer, a close will always also flush. This basically means that you have to consult the documentation of the concrete classes that you are using when trying to find out what closing really does.
The resources are automatically closed when using try-with-resource block. As part of this process it will also invoke flush automatically.
As mentioned in doc for close method of BufferedWriter:
Closes the stream, flushing it first. Once the stream has been closed,
further write() or flush() invocations will cause an IOException to be
thrown.
Quoting javadoc of BufferedWriter.close():
Closes the stream, flushing it first.
The minimum amount of code to be written in this case:
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
bw.write("Test");
} catch (IOException e) {
// handle exception
}
Hence you don't need to call explicitly the flush method, as it will be called by the close method, as explained in the javadoc:
Closes the stream, flushing it first. Once the stream has been closed,
further write() or flush() invocations will cause an IOException to be
thrown. Closing a previously closed stream has no effect.
This behavior is inherited from the Writer class, hence besides BufferedWriter the same behavior is provided also by: CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter.
This behavior is not provided in the documentation of the tryWithResources or AutoCloseable as the behavior is specific to the given implementation of Writer. As Writerextends Closeable, it will call the close method when exiting the try {} block and the close method will first call
flush as already mentioned.
I really don't understand why other answers focus on the BufferedWriter not try-with-resources.
I, either, couldn't find any specification or mentions that the try-with-resources statements calls flush() on any objects of Flushable.
https://docs.oracle.com/javase/specs/jls/se13/html/jls-14.html#jls-14.20.3
Don't rely on any undocumented/unspecified behavior of vendor specific implementations.
try (OutputStream o = open()) {
//writeSome
o.flush(); // won't hurt!
}
From the Javdocs:
The try-with-resources statement is a try statement that declares one
or more resources. A resource is an object that must be closed after
the program is finished with it. The try-with-resources statement
ensures that each resource is closed at the end of the statement. Any
object that implements java.lang.AutoCloseable, which includes all
objects which implement java.io.Closeable, can be used as a
resource.
The BufferedWriter.close() explicitly stated that:
Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.
In Java 7, there is a try-with syntax that ensures objects like InputStream are closed in all code paths, regardless of exceptions. However, the variable declared in the try-with block ("is") is final.
try (InputStream is = new FileInputStream("1.txt")) {
// do some stuff with "is"
is.read();
// give "is" to another owner
someObject.setStream(is);
// release "is" from ownership: doesn't work because it is final
is = null;
}
Is there a concise syntax to express this in Java? Consider this exception-unsafe method. Adding the relevant try/catch/finally blocks would make the method much more verbose.
InputStream openTwoFiles(String first, String second)
{
InputStream is1 = new FileInputStream("1.txt");
// is1 is leaked on exception
InputStream is2 = new FileInputStream("2.txt");
// can't use try-with because it would close is1 and is2
InputStream dual = new DualInputStream(is1, is2);
return dual;
}
Obviously, I can have the caller open both files, placing them both in a try-with block. This is only one example of a case where I want to perform some operation on a resource before transferring ownership of it to another object.
The try-with is intended to be used in a situation where the identified resource must never persist outside the scope of the try block.
If you want to use the try-with construction, you must change your design as follows:
Delete the openTwoFiles() method. it is value free.
Create a constructor for the DualInputStream class that takes two file names and creates the two InputStreams. Declare that this constructor throws IOException and allow it to throw IOExceptions.
Use the new constructor in a try-with construct.
If I invoke a BufferedReader the following way:
Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());
Will the JVM know to automatically close it when not in use? If not, how do I go about closing it?
If you are using java 7 or greater and your code is in try catch resource block, then it is Auto closes.
If in below versions you have to close with close(). For that you have to change your current way of using and get the reference.
Don't chain them, declare and assign variables, then close it after the usage.
InputStreamReader isReader;
BufferedReader bfReader;
try {
isReader = new InputStreamReader(System.in);
bfReader = new BufferedReader(isReader).readLine();
} catch (Exception e) {
// handle as per the requirement.
} finally {
bfReader.close();
}
If you use java 7, then, if you defined withing the try clause, then those will auto closable. Check here for more details
The try-with-resources statement is a try statement that declares one
or more resources. A resource is as an object that must be closed
after the program is finished with it. The try-with-resources
statement ensures that each resource is closed at the end of the
statement. Any object that implements java.lang.AutoCloseable, which
includes all objects which implement java.io.Closeable, can be used as
a resource.
I'm trying to delete a file that another thread within my program has previously worked with.
I'm unable to delete the file but I'm not sure how to figure out which thread may be using the file.
So how do I find out which thread is locking the file in java?
I don't have a straight answer (and I don't think there's one either, this is controlled at OS-level (native), not at JVM-level) and I also don't really see the value of the answer (you still can't close the file programmatically once you found out which thread it is), but I think you don't know yet that the inability to delete is usually caused when the file is still open. This may happen when you do not explicitly call Closeable#close() on the InputStream, OutputStream, Reader or Writer which is constructed around the File in question.
Basic demo:
public static void main(String[] args) throws Exception {
File file = new File("c:/test.txt"); // Precreate this test file first.
FileOutputStream output = new FileOutputStream(file); // This opens the file!
System.out.println(file.delete()); // false
output.close(); // This explicitly closes the file!
System.out.println(file.delete()); // true
}
In other words, ensure that throughout your entire Java IO stuff the code is properly closing the resources after use. The normal idiom is to do this in the try-with-resources statement, so that you can be certain that the resources will be freed up anyway, even in case of an IOException. E.g.
try (OutputStream output = new FileOutputStream(file)) {
// ...
}
Do it for any InputStream, OutputStream, Reader and Writer, etc whatever implements AutoCloseable, which you're opening yourself (using the new keyword).
This is technically not needed on certain implementations, such as ByteArrayOutputStream, but for the sake of clarity, just adhere the close-in-finally idiom everywhere to avoid misconceptions and refactoring-bugs.
In case you're not on Java 7 or newer yet, then use the below try-finally idiom instead.
OutputStream output = null;
try {
output = new FileOutputStream(file);
// ...
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
}
Hope this helps to nail down the root cause of your particular problem.
About this question, I also try to find out this answer, and ask this question and find answer:
Every time when JVM thread lock a file exclusively, also JVM lock
some Jave object, for example, I find in my case:
sun.nio.fs.NativeBuffer
sun.nio.ch.Util$BufferCache
So you need just find this locked Java object and analyzed them and
you find what thread locked your file.
I not sure that it work if file just open (without locked exclusively), but I'm sure that is work if file be locked exclusively by Thread (using java.nio.channels.FileLock, java.nio.channels.FileChannel and so on)
More info see this question