I realize that in java the GC will eventually cleanup objects, but I'm asking if it is bad practice to not close your string writer, currently I am doing this:
private static String processTemplate(final Template template, final Map root) {
StringWriter writer = new StringWriter();
try {
template.process(root, writer);
} catch (TemplateException e) {
logger.error(e.getMessage());
} catch (IOException e) {
logger.error(e.getMessage());
}
finally {
}
return writer.toString();
}
Should I be closing the writer and creating a new String like this:
String result = "";
...
finally {
result = writer.toString();
writer.close();
}
Is this better to do?
The javadoc is quite explicit:
Closing a StringWriter has no effect.
And a quick look at the code confirms it:
public void close() throws IOException {
}
It's not holding any non-memory resource. It will be garbage collected like anything else.
The close() probabaly merely exists because other writer objects do hold resources that need to be cleaned up, and the close() is needed to satify the interface.
No, not closing a StringWriter will not cause a leak: as noted, StringWriter#close() is a nop, and the writer only holds memory, not external resources, so these will be collected when the writer is collected. (Explicitly, it holds references to objects in private fields that do not escape the object, concretely a StringBuffer, so no outside references.)
Further, you generally shouldn't close a StringWriter, because it adds boilerplate to your code, obscuring the main logic, as we'll see. However, to reassure readers that you're being careful and doing this intentionally, I'd recommend commenting this fact:
// Don't need to close StringWriter, since no external resource.
Writer writer = new StringWriter();
// Do something with writer.
If you do want to close the writer, most elegant is to use try-with-resources, which will automatically call close() when you exit the body of the try block:
try (Writer writer = new StringWriter()) {
// Do something with writer.
return writer.toString();
}
However, since Writer#close() throws IOException, your method now needs to also throw IOException even though it never occurs, or you need to catch it, to prove to the compiler that it is handled. This is quite involved:
Writer writer = new StringWriter();
try {
// Do something with writer, which may or may not throw IOException.
return writer.toString();
} finally {
try {
writer.close();
} catch (IOException e) {
throw new AssertionError("StringWriter#close() should not throw IOException", e);
}
}
This level of boilerplate is necessary because you can't just put a catch on the overall try block, as otherwise you might accidentally swallow an IOException thrown by the body of your code. Even if there isn't any currently, some might be added in future and you'd want to be warned of this by the compiler. The AssertionError is documenting the current behavior of StringWriter#close(), which could potentially change in a future release, though that is extremely unlikely; it also masks any exception that may occur in the body of the try (again, this should never occur in practice). This is far too much boilerplate and complexity, and you'd clearly be better off omitting the close() and commenting why.
A subtle point is that not only does Writer#close() throw an IOException, but so does StringWriter#close(), so you can't eliminate the exception by making the variable a StringWriter instead of a Writer. This is different from StringReader, which overrides the close() method and specifies that it does not throw an exception! See my answer to Should I close a StringReader?. This may look wrong – why would you have a method that does nothing but may throw an exception?? – but is presumably for forward compatibility, to leave open the possibility of throwing an IOException on close in future, as this is an issue for writers generally. (It could also just be a mistake.)
To summarize: it's fine to not close a StringWriter, but the reason to not do the usual right thing, namely try-with-resources, is just because close() declares that it throws an exception that it doesn't actually throw in practice, and handling this precisely is a lot of boilerplate. In any other case it's better to just use the conventionally correct resource-management pattern and prevent problems and head-scratching.
At the end of the method there is no reference left to the writer therefore it will be freed by the GC.
Related
I have a class which implements read and write operation to file in a concurrent environment. I know BufferedInputStream and BufferedWriter are synchronized but in my case read and write operations can be used simultaneously. Now I use ReentrantReadWriteLock but I'm not confident about a solution correctly.
public class FileSource {
private final File file;
private final ReadWriteLock lock;
public FileWrapper(final File file) {
if (Objects.isNull(file)) {
throw new IllegalArgumentException("File can't be null!");
}
this.file = file;
this.lock = new ReentrantReadWriteLock();
}
public String getContent() {
final Lock readLock = lock.readLock();
readLock.lock();
final StringBuilder sb = new StringBuilder();
try (final BufferedInputStream in =
new BufferedInputStream(
new FileInputStream(file))) {
int data;
while ((data = in.read()) > 0) {
sb.append(data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
readLock.unlock();
}
return sb.toString();
}
public void saveContent(final String content) {
final Lock writeLock = lock.writeLock();
writeLock.lock();
try (BufferedWriter out =
new BufferedWriter(
new FileWriter(file))) {
out.write(content);
} catch (IOException e) {
e.printStackTrace();
} finally {
writeLock.unlock();
}
}
}
ReentrantReadWriteLock is the correct solution in this case or I need to use ReentrantLock or something else? (with a reason)
This discussion not about class design like File as a state or send File directly in the method or using nio package or ext. It shouldn't be a utility class. Method signatures and File as a field must stay without changes. It is about potential concurrency problems with File and InputStream\OutputStream.
RRWL is fine here. Of course, if some code makes a new FileWrapper("/foo/bar.txt") and then some other code also makes a separate new FileWrapper("/foo/bar.txt") those two wrappers will be falling all over themselves and will cause things to go pearshaped; I assume you have some external mechanism to ensure this cannot happen. If you don't, some take on ConcurrentHashMap and its concurrency methods (such as computeIfAbsent; don't use the plain jane get/put for these) can help you out.
Note that your exception handling is bad. Exception messages should not end in punctuation (think about it: Without this rule, 80% of all exception messages would end in an exclamation mark and will make log files a fun exercise), and in general, if you ever write catch (Exception e) { e.printStackTrace(); }, you go to that special place reserved for people who talk in movie theaters, and people who write that.
I'd say a method called saveContent is justified in throwing some checked exception; after all, it's rather obvious that can fail, and code calling it can feasibly be expected to perhaps take some action if it does.
If you just can't get there, the proper ¯\(ツ)/¯ I dunno catch block handler is: throw new RuntimeException("uncaught", e);. Not e.printStackTrace();. The latter logs to an uncontrollable place, shaves off useful information, and crucially, keeps on running as if nothing is wrong, silently ignoring the fact that a save call just failed, whereas the former preserves all and will in fact abort code execution. It makes it hard to recover, but at least it's easier than e.printStackTrace, and if you wanted it to be easier, than make a special exception. Or just throw that IOException unmolested (you get way shorter code to boot!).
Another insiduous bug in this code is that it uses 'platform default charset encoding' to read your file, which is very rarely what you want.
The new Files API can also read the entire file in one go, saves you a ton of code on that read op. As you upgrade your code, you get the benefit of the Files API's unique take on charset encodings: Unlike most other places in the java libraries, java.nio.file.Files will assume you meant to use UTF-8 encoding if you fail to specify (instead of 'platform default', i.e. 'the thing that you cannot test for that will blow up in production and waste a week of your time chasing after it').
With the following code:
try {
throw new RuntimeException ("main");
}
finally {
throw new RuntimeException ("finally");
}
I get this result:
Exception in thread "main" java.lang.RuntimeException: finally
at test.main(test.java:12)
However, with the addition of suppressed exceptions in Java 7, wouldn't it be logical for the language to register original "main" exception as suppressed when finally block itself fails with exception? Currently I have to manually emulate this:
try {
throw new RuntimeException ("main");
}
catch (RuntimeException exception) {
try {
throw new RuntimeException ("finally");
}
catch (RuntimeException exception2) {
exception2.addSuppressed (exception);
throw exception2;
}
}
to receive more useful (for understanding what's going on) result:
Exception in thread "main" java.lang.RuntimeException: finally
at test.main(test.java:13)
Suppressed: java.lang.RuntimeException: main
at test.main(test.java:9)
EDIT: To clarify what I'm wondering. Current Java version is 8, suppressed exceptions are not a brand new feature. But try..finally still doesn't incorporate them. Is there something that prevents this from happening?
Because try-with-resources is syntactic sugar and the Java compiler doesn't expand regular try-finally blocks in the same way.
Take a look at the following code:
try(FileInputStream fstream = new FileInputStream("test")) {
fstream.read();
}
When compiled and then decompiled (using IntelliJ IDEA) it looks like this:
FileInputStream fstream = new FileInputStream("test");
Throwable var2 = null;
try {
fstream.read();
} catch (Throwable var19) {
var2 = var19;
throw var19;
} finally {
if(fstream != null) {
if(var2 != null) {
try {
fstream.close();
} catch (Throwable var17) {
var2.addSuppressed(var17);
}
} else {
fstream.close();
}
}
}
Whereas this code:
FileInputStream fstream = new FileInputStream("test");
try {
fstream.read();
} finally {
fstream.close();
}
Looks exactly the same when compiled and decompiled.
Now, the case could definitely be made that all finally blocks should be expanded in the same way as is done above, but for some reason that has either been overlooked or decided against.
I suggest you open a feature request for this because I think it's a sensible feature.
This isn't an authoritative answer but it looks like such a change would either break compatibility, or try-with-resources and try-finally would be inconsistent with each other.
The semantics in try-with-resources is that the exception thrown from the try block is propagated, with the exception thrown when invoking the close() method registered as suppressed. This makes sense from a practical point of view, you want to catch your "real" exception and then maybe also deal with the resource not closing if you want to.
But in try-finally it is the exception thrown in finally that is propagated (while the one from try is "swallowed") and therefore we have a choice of three bad solutions:
Reverse the logic of try-finally to align it with try-with-resources and ruin code (or rather, bug) compatibility with all previous code.
Keep propagating the "close()" exception with the try exception registered as suppressed, making the two constructs inconsistent with each other.
Just leave everything as it is.
Subjectively I see 3 as less bad than 1 or 2, though it's fairly easy to argue otherwise. I suspect however that this was a dilemma the language developers were faced with and they happened to choose option 3.
I've got a doubt about using the try/catch/finally clauses,let me explain:
I know that every method which declares an exception specification in its declaration has to be surrounded (in a calling method) with a try block,followed by a catch block that can capture that exception (unless I don't declare the calling method throwing an exception as well). If the calling method has other statements after the try-catch, those are executed regardless of what happens (exception thrown or not). So if I have the following code:
public class ExceptionCall {
Throwing t = new Throwing();
public void methodTry(){
while(true){
try {
if (t.flag++==0)
t.throwing();
System.out.println("no exception");
}
catch (MyException e) {
e.printStackTrace(System.err);
System.out.println("working on it!");
}
finally{
System.out.println("finally clause");
}
System.out.println("out");
if (t.flag==2)
break;
}
}
}
Here Throwing has a method called (guess what :) ) throwing() which is declared to throw a MyException exception, and has a public field called flag containing an int initialized to 0 to provide a sort of condition checking.
So for a couple of times the code outside the guarded region is executed no matter what happens in the try block.
So my question is, what is the finally block for?? I mean, I know it comes in handy when the calling method returns from the try or the catch block (in this case I could have a break statement inside the catch and the finally would be executed), but in a case like this what's the difference??
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.
See : https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
Finally block is used to handle those resources that need you to make some action at the end of the statement no matter what happens in the code.
For example: readers or streams are resources that must be closed after it's use, but exceptions can happen during it's usage, so where you close them???
Here is where finally clause becomes really handy:
FileReader reader;
try {
reader = new FileReader("someNonExistingFile");
} catch (FileNotFoundException e) {
// handle FileNotFoundException
e.printMessage();
} finally {
// reader MUST BE CLOSED ALWAYS, so FINALLY, CLOSE IT
reader.close();
}
In this example, you need to close reader always (if file exists and if file doesn't) so, instead of closing it twice (in try and in catch) you use finally.
Further info and examples of finally here. Also check try with resources (Java 7+).
Could someone explain me some situation (example) when we can use this construction?
try{
//dangerous code here
} finally {
//always called
}
I really understand how it works but newer use in real situation.
Pretty much any time you have something like a Closeable, where you need to explicitly call close() to release the underlying resource, you want to put that call in a finally block, like:
FileReader f = whatever();
try {
// do some stuff with f
return;
}
finally {
f.close();
}
Even if no exception is thrown, and the return inside the try block is run, the resource will still be closed correctly.
try {
isWorking = true
//doStuff that might or might not succeed
} finally {
isWorking = false;
}
another example:
public void actionPressed()
{
if( isLoading )
return;
try {
isLoading= true;
doTheLoad);
} finally {
isLoading = false;
}
}
Some of the common scenarios:
Prevent resource leak:
Close IO streams and DB connections
Message logging
You might use it close database connections or any other resource - a file, hardware port, etc.
try{
// Do something I care about
} finally {
// Make sure we clean up, regardless of success or failure
}
Here's an example:
InputStream in = new FileInputStream(...);
try {
/ * use in here */
} finally {
in.close();
}
Basically, no matter what happens, in will always be closed. Without this, in could stay open until the garbage collector collects it (could be a long time). This is a problem because:
There is a limit on the number of files / network connections you can have open at once
Open network connections will continue to tie up resources on the remote end too (DB connections are a good example)
Closing an input stream also flushes it generally (flushing writes anything in the inputstream's buffer)
For instance when you read a file:
InputStream is = new FileInputStream("...");
try {
// do stuff
}
finally {
is.close();
}
This way your file is always closed, even if there is an exception.
openFile();
try {
int i = Integer.parseInt(someString);
String sub = someString.substring(2);
System.out.println(i+sub);
}
finally {
closeFile();
}
as you can see, there might several Exceptions be thrown during a code passage and you possibly don't want to catch every of them.
also there could an Error be thrown, which you should not catch!
in any way you want to close your file, before the method ends, so you put that in the finally-block
Look at this article, Java Exception Handling - Basics. Here described clearly about exception and where it is used.
This is a very common pattern:
InputStream stream = // acquire stream...
try {
// do stuff with stream that might throw...
}
finally {
IOUtils.closeQuietly(stream);
}
Note, IOUtils is a library from the Apache Commons project. You should always close the stream in a finally. closeQuietly eats any exceptions that might be thrown while trying to close the stream (which is OK because you can't do anything about it).
Especially we can use for data base connection close related code in finally block. if program throws any exception in this case DB connection will release .
This is example in JDBC.same can be applicable in session.close() in Hibernate.
try{
//dangerous code here
} catch(Exception e){
//Do some thing releted to your exception
} finally {
//close DB connection or close your hibernate session.
//always called
}
Well, let's say you open a connection to a database and make some queries. If a SQLException is raised by one of the queries, you're supposed to close the connection before doing something else. If no exception is raised, you're still supposed to close it.
So the try {} catch () {} is there to catch those SQLExceptions and do something about them, while the finally {} is there to close the connection in either case.
This would be a very common scenario, but the same is true with any resource that needs to be freed no matter what happens while using it.
I just played with Java file system API, and came down with the following function, used to copy binary files. The original source came from the Web, but I added try/catch/finally clauses to be sure that, should something wrong happen, the Buffer Streams would be closed (and thus, my OS ressources freed) before quiting the function.
I trimmed down the function to show the pattern:
public static void copyFile(FileOutputStream oDStream, FileInputStream oSStream) throw etc...
{
BufferedInputStream oSBuffer = new BufferedInputStream(oSStream, 4096);
BufferedOutputStream oDBuffer = new BufferedOutputStream(oDStream, 4096);
try
{
try
{
int c;
while((c = oSBuffer.read()) != -1) // could throw a IOException
{
oDBuffer.write(c); // could throw a IOException
}
}
finally
{
oDBuffer.close(); // could throw a IOException
}
}
finally
{
oSBuffer.close(); // could throw a IOException
}
}
As far as I understand it, I cannot put the two close() in the finally clause because the first close() could well throw, and then, the second would not be executed.
I know C# has the Dispose pattern that would have handled this with the using keyword.
I even know better a C++ code would have been something like (using a Java-like API):
void copyFile(FileOutputStream & oDStream, FileInputStream & oSStream)
{
BufferedInputStream oSBuffer(oSStream, 4096);
BufferedOutputStream oDBuffer(oDStream, 4096);
int c;
while((c = oSBuffer.read()) != -1) // could throw a IOException
{
oDBuffer.write(c); // could throw a IOException
}
// I don't care about resources, as RAII handle them for me
}
I am missing something, or do I really have to produce ugly and bloated code in Java just to handle exceptions in the close() method of a Buffered Stream?
(Please, tell me I'm wrong somewhere...)
EDIT: Is it me, or when updating this page, I saw both the question and all the answers decreased by one point in a couple of minutes? Is someone enjoying himself too much while remaning anonymous?
EDIT 2: McDowell offered a very interesting link I felt I had to mention here:
http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html
EDIT 3: Following McDowell's link, I tumbled upon a proposal for Java 7 of a pattern similar to the C# using pattern: http://tech.puredanger.com/java7/#resourceblock . My problem is explicitly described. Apparently, even with the Java 7 do, the problems remain.
The try/finally pattern is the correct way to handle streams in most cases for Java 6 and lower.
Some are advocating silently closing streams. Be careful doing this for these reasons: Java: how not to make a mess of stream handling
Java 7 introduces try-with-resources:
/** transcodes text file from one encoding to another */
public static void transcode(File source, Charset srcEncoding,
File target, Charset tgtEncoding)
throws IOException {
try (InputStream in = new FileInputStream(source);
Reader reader = new InputStreamReader(in, srcEncoding);
OutputStream out = new FileOutputStream(target);
Writer writer = new OutputStreamWriter(out, tgtEncoding)) {
char[] buffer = new char[1024];
int r;
while ((r = reader.read(buffer)) != -1) {
writer.write(buffer, 0, r);
}
}
}
AutoCloseable types will be automatically closed:
public class Foo {
public static void main(String[] args) {
class CloseTest implements AutoCloseable {
public void close() {
System.out.println("Close");
}
}
try (CloseTest closeable = new CloseTest()) {}
}
}
There are issues, but the code you found lying about on the web is really poor.
Closing the buffer streams closes the stream underneath. You really don't want to do that. All you want to do is flush the output stream. Also there's no point in specifying the underlying streams are for files. Performance sucks because you are copying one byte at a time (actually if you use java.io use can use transferTo/transferFrom which is a bit faster still). While we are about it, the variable names suck to. So:
public static void copy(
InputStream in, OutputStream out
) throw IOException {
byte[] buff = new byte[8192];
for (;;) {
int len = in.read(buff);
if (len == -1) {
break;
}
out.write(buff, 0, len);
}
}
If you find yourself using try-finally a lot, then you can factor it out with the "execute around" idiom.
In my opinion: Java should have someway of closing resources at end of scope. I suggest adding private as a unary postfix operator to close at the end of the enclosing block.
Unfortunately, this type of code tends to get a bit bloated in Java.
By the way, if one of the calls to oSBuffer.read or oDBuffer.write throws an exception, then you probably want to let that exception permeate up the call hierarchy.
Having an unguarded call to close() inside a finally-clause will cause the original exception to be replaced by one produced by the close()-call. In other words, a failing close()-method may hide the original exception produced by read() or write(). So, I think you want to ignore exceptions thrown by close() if and only if the other methods did not throw.
I usually solve this by including an explicit close-call, inside the inner try:
try {
while (...) {
read...
write...
}
oSBuffer.close(); // exception NOT ignored here
oDBuffer.close(); // exception NOT ignored here
} finally {
silentClose(oSBuffer); // exception ignored here
silentClose(oDBuffer); // exception ignored here
}
static void silentClose(Closeable c) {
try {
c.close();
} catch (IOException ie) {
// Ignored; caller must have this intention
}
}
Finally, for performance, the code should probably work with buffers (multiple bytes per read/write). Can't back that by numbers, but fewer calls should be more efficient than adding buffered streams on top.
Yes, that's how java works. There is control inversion - the user of the object has to know how to clean up the object instead of the object itself cleaning up after itself. This unfortunately leads to a lot of cleanup code scattered throughout your java code.
C# has the "using" keyword to automatically call Dispose when an object goes out of scope. Java has no such thing.
For common IO tasks such as copying a file, code such as that shown above is reinventing the wheel. Unfortunately, the JDK doesn't provide any higher level utilities, but apache commons-io does.
For example, FileUtils contains various utility methods for working with files and directories (including copying). On the other hand, if you really need to use the IO support in the JDK, IOUtils contains a set of closeQuietly() methods that close Readers, Writers, Streams, etc. without throwing exceptions.