So i have been going through "Effective Java 2nd Ed."
In item 7 he talks about not using finalizers because they can cause a lot of problems .
But instead of using finalizers we can " provide an explicit termination method" and an example of those is the close statement . and i did not understand what is " termination statements and what are the differences between them and finalizers ?
I came to the conclusion that terminating an object is like nulling it thus the resourses is released . but i think i don`t understand the difference that well . so i appreciate any help .
Thanks !
But instead of using finalizers we can " provide an explicit
termination method" and an example of those is the close statement .
The authors refers to a close() method that provides a way to clean an object that uses resources to free.
For example when you create and manipulate an InputStream or an OutputStream, you don't want to rely on Java finalizers (that may exist for some subclasses of these interface. For example it is the case for the FileInputStream class that defines a finalize() method) to release the resources associated to the stream but you want to use the method provided by the API to do it : void close() as it is more reliable as finalizer.
java.sql.Statement works in the same way : it provides a close() method to release JDBC resources associated to the statement instance.
I came to the conclusion that terminating an object is like nulling it
thus the resourses is released .
Assigning an object to null will not necessary free all resources that should be freed. Besides if the object or a field of the object is still referenced by another living object, the object would be not illegible to be garbage collected
At last, being garbage collected may also take a some time.
Why wait if we don't need to use the object ?
The main difference between an explicit termination method and finalize() is that the second one is not guaranteed to be called. It's called eventually during garbage collection which might to be honest never occur. Lets consider the following three classes.
class Foo {
#Override
public void finalize() {
System.out.println("Finalize Foo");
}
}
class Bar implements Closeable {
#Override
public void close() {
System.out.println("Close Bar");
}
}
class Baz implements AutoCloseable {
#Override
public void close() {
System.out.println("Close Baz");
}
}
The first one overrides the finalize() method inherited from Object. Foo and Bar implement both interfaces which are handled by ARM (Automatic Resource Management).
Foo foo = new Foo();
new Foo();
try (Bar bar = new Bar(); Baz baz = new Baz()) { // this is ARM
System.out.println("termination example");
}
Bar bar = null;
try {
bar = new Bar();
// ...
} finally {
if (bar != null) {
bar.close();
}
}
This example should return:
termination example
Close Baz
Close Bar
Close Bar
The finalize() method of Foo gets never called because Foo is not garbage collected. The JVM has available resources, so for performance optimization it does not perform garbage collecting. Furthermore - if a resource isn't garbage collected despite the fact of finishing the Application. Even the second created instance of Foo is not Garbage Collected, because there is plenty of resources for the JVM to thrive.
The second one with ARM is a lot better, because it creates both the resources (one implementing java.io.Closeable and one implementing java.lang.AutoCloseable, it's worth mentioning that Closeable extends AutoCloseable, that's why it's available for ARM). ARM guaranties for both of these resources to be closed, to close one when the other throws and so on. The second one presents something similar to ARM, but saving a lot of unnecessary boilerplate code.
Something making you a better developer:
But it's still not perfect. There is still a burden on the programmer to remember closing the object. The absence of destructors in Java forces the developer either to remember closing the resource, remember to use ARM and so on. There is a good design pattern (good explained by Venkat Subramaniam) - the Loan Pattern. A simple example of the loan pattern:
class Loan {
private Loan() {
}
public Loan doSomething(int m) {
System.out.println("Did something " + m);
if (new Random().nextBoolean()) {
throw new RuntimeException("Didn't see that commming");
}
return this;
}
public Loan doOtherThing(int n) {
System.out.println("Did other thing " + n);
return this;
}
private void close() {
System.out.println("Closed");
}
public static void loan(Consumer<Loan> toPerform) {
Loan loan = new Loan();
try {
toPerform.accept(loan);
} catch (Exception e) {
e.printStackTrace();
} finally {
loan.close();
}
}
}
You can use it like that:
class Main {
public static void main(String[] args) {
Loan.loan(loan -> loan.doOtherThing(2)
.doSomething(3)
.doOtherThing(3));
}
}
It relieves the developer of the burden of closing the resource, because it has already been handled for him. If one of these methods throws, then it's handled and the developer does not have to bother. The close method and constructor are private to not tempt the developer to use them.
Related
I have a continuously running service that I want stopped cleanly if it hits an exception. This fits well with the try with resources paradigm but it's not really a resource that needs to be "closed".
To clarify based on comments, my code looks something like this
class Service {
Resource resource;
State state;
boolean keepRunning = false;
void start() {
keepRunning = true;
resource = new Resource()
new Thread(() -> {
while(keepRunning) {
Data data = resources.pull();
state.update(data);
... // Do stuff with state
}
}).start();
}
void stop() {
keepRunning = false;
}
}
class Main {
void run() {
Service service = new Service();
service.start();
}
}
Is there a pattern that lets me use the syntactic sugar that try-with-resources provides while still not abusing try-with-resources with things that are not resources?
Of course, it is totally okay to use try-with-resources with anything you want. The requirement is that it implements the interface AutoCloseable (documentation). With that interface you will need to implement a close method, which then is called by the try-with-resources construct.
That is why this interface is there, you are allowed to implement it for your own classes.
For example if you have a service that needs to be probably shut down, also in error case, you may use AutoCloseable and implement the close method probably.
However it's meaningless and will confuse readers of your program if you make something AutoCloseable where there is totally no intuition what close means on this object. In such cases you should probably look for other constructs.
It's a bit like implementing Iterable such that you can use the enhanced for loop like:
for (Item item : myObject) {
...
}
You may do it, if it makes sense. Otherwise it will confuse people.
With my server application I'm using a list of WeakReferences to keep count and handle active sessions to server. I'm running periodic gc to clean the list of inactive sessions, but for some reason one reference always remains. According to overridden finalize method this is the last sessions created.
I'm clueless on why this is happening. I first thought this may have been due to static methods or variables, but for now i have removed such objects from ClientHandlerThread class. There are no other references from the server class but the weak references list. Currently this is not a big issue for me, but to have better understanding on how java selects objects to be garbage collected can be of use in the future. :) Below are most important code snippets:
Server.java:
public class Server {
private List<WeakReference<ClientHandlerThread>> m_connectedClients =
Collections.synchronizedList(
new ArrayList<WeakReference<ClientHandlerThread>>());
/** Counter to identify sessions */
private static AtomicInteger m_NumSession = new AtomicInteger(0);
Server() {
SSLServerSocket sslDataTraffic = null;
// Sockets are initialized here - code removed for clarity
// Run periodic GC
Thread stThread = new Thread() {
public void run() {
do {
try {
Thread.sleep(5000);
}
catch (InterruptedException ignore) {}
System.runFinalization();
System.gc();
cleanUpSessionsList();
} while (true);
}
};
stThread.setPriority(Thread.MIN_PRIORITY);
stThread.start();
// Listen to new connections, create handlers and add to list
while (true) {
try {
SSLSocket sslDataTrafficSocketInstance =
(SSLSocket) sslDataTraffic.accept();
ClientHandlerThread c = new ClientHandlerThread(
sslDataTrafficSocketInstance,
m_NumSession.incrementAndGet());
c.start();
m_connectedClients.add(new WeakReference<>(c));
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** Clean any old references and return the number of active connections
* #return
*/
public int cleanUpSessionList() {
int i = 0;
synchronized(m_connectedClients) {
Iterator<WeakReference<ClientHandlerThread>> it =
m_connectedClients.iterator();
while (it.hasNext()) {
WeakReference<ClientHandlerThread> sessionRef = it.next();
if (sessionRef.get() == null)
it.remove();
else
i++;
}
}
System.out.println("Active sessions: " + i");
return i;
}
}
ClientHandlerThread.java:
public class ClientHandlerThread extends Thread {
private int m_SessionID;
private SSLSocket dataSocket;
public ClientHandlerThread(
SSLSocket dataSocket,
int sessionID) {
this.dataSocket = dataSocket;
m_SessionID = sessionID;
}
public void run() {
// code removed
}
#Override
protected void finalize() throws Throwable {
System.out.println("Session " + m_SessionID + " finalized");
super.finalize();
}
}
That's about all wrong (the code itself isn't bad, but you're doing many things I'd usually avoid).
Use a ReferenceQueue instead of finalize.
Consider using a PhantomReference instead of weak as you AFAICT don't need to access the referee.
If all you want is to count active sessions, the simply count them (surround the handler code by session tracking code).
You should use a thread pool.
Running periodic GC can impact performance (though it may even help the performance, you should not rely on it).
Concerning the question itself... no idea, but there may be something in the code blocking the last thread from freeing. as already suggested, perform a heap snapshot, run it through a memory analyzer.
Found this question as a cross-reference after I posted a related question.
I don't have an answer as to why it's happening, and I think it shouldn't, but I can tell you what I think is happening, and I'm curious if a suggested workaround changes the behavior you're seeing. (If you still have the code lying around; I know it's an older question.)
As far as I can tell, somehow the JRE maintains a reference to the last scoped variable that gets created. By setting the variable to null (or by creating another, new, unrelated scoped variable) this problem goes away.
So something like this:
ClientHandlerThread c = new ClientHandlerThread(
sslDataTrafficSocketInstance,
m_NumSession.incrementAndGet());
c.start();
m_connectedClients.add(new WeakReference<>(c));
c = null;
Again, I'm not saying it should behave this way, but from the testing I've done in my similar situation, it works.
I am having problems with Phantom References when referents are the fields inside the class. When class objects are set to null, fields are not collected automatically by GC
Controller.java
public class Controller {
public static void main( String[] args ) throws InterruptedException
{
Collector test = new Collector();
test.startThread();
Reffered strong = new Reffered();
strong.register();
strong = null; //It doesn't work
//strong.next =null; //It works
test.collect();
Collector.m_stopped = true;
System.out.println("Done");
}
}
Collector.java: I am having a Collector that registers an object to reference queue and prints it when it is collected.
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import java.util.Map;
public class Collector {
private static Thread m_collector;
public static boolean m_stopped = false;
private static final ReferenceQueue refque = new ReferenceQueue();
Map<Reference,String> cleanUpMap = new HashMap<Reference,String>();
PhantomReference<Reffered> pref;
public void startThread() {
m_collector = new Thread() {
public void run() {
while (!m_stopped) {
try {
Reference ref = refque.remove(1000);
System.out.println(" Timeout ");
if (null != ref) {
System.out.println(" ref not null ");
}
} catch (Exception ex) {
break;
}
}
}
};
m_collector.setDaemon(true);
m_collector.start();
}
public void register(Test obj) {
System.out.println("Creating phantom references");
//Referred strong = new Referred();
pref = new PhantomReference(obj, refque);
cleanUpMap.put(pref, "Free up resources");
}
public static void collect() throws InterruptedException {
System.out.println("GC called");
System.gc();
System.out.println("Sleeping");
Thread.sleep(5000);
}
}
Reffered.java
public class Reffered {
int i;
public Collector test;
public Test next;
Reffered () {
test= new Collector();
next = new Test();
}
void register() {
test.register(next);
}
}
Test is a empty class. I can see that "next" field in Refferred class is not collected when Reffered object is set to null. In other words, when "strong" is set to null, "next" is not collected. I assumed that "next" will be automatically collected by GC because "next" is no more referenced when "strong" is set to null. However, when "strong.next" is set to null, "next" is collected as we think. Why is "next" not collected automatically when strong is set to null?
You have a very confusing code structure.
At the beginning of your code, you have the statements
Collector test = new Collector();
test.startThread();
so you are creating an instance of Collector that the background thread will have a reference to. That thread isn’t even touching that reference, but since it is an anonymous inner class, it will hold a reference to its outer instance.
Within Reffered you have a field of type Collector that is initialized with new Collector() in the constructor, in other words, you are creating another instance of Collector. This is the instance on which you invoke register.
So all artifacts created by register, the PhantomReference held in pref and the HashMap held in cleanUpMap, which has also a reference to the PhantomReference, are only referenced by the instance of Collector referenced by Reffered. If the Reffered instance becomes unreachable, all these artifacts become unreachable too and nothing will be registered at the queue.
This is the place to recall the java.lang.ref package documentation:
The relationship between a registered reference object and its queue is one-sided. That is, a queue does not keep track of the references that are registered with it. If a registered reference becomes unreachable itself, then it will never be enqueued. It is the responsibility of the program using reference objects to ensure that the objects remain reachable for as long as the program is interested in their referents.
There are some ways to illustrate the issue with your program.
Instead of doing either, strong = null; or strong.next = null;, you may do both:
strong.next = null;
strong = null;
here, it doesn’t matter that next has been nulled out, this variable is unreachable anyway, once strong = null has been executed. After that, the PhantomReference that was only reachable through the Reffered instance has become unreachable itself and no “ref not null” message will be printed.
Alternatively, you may change that code part to
strong.next = null;
strong.test = null;
which will also make the PhantomReference unreachable, thus never enqueued.
But if you change it to
Object o = strong.test;
strong = null;
the message “ref not null” will be printed as o holds an indirect reference to the PhantomReference. It must be emphasized that this is not guaranteed behavior, Java is allowed to eliminate the effect of unused local variables. But it is sufficiently reproducible with the current HotSpot implementation to demonstrate the point.
The bottom line is, the Test instance has been always collected as expected. It’s just that in some cases, more has been collected than you were aware of, including the PhantomReference itself, so no notification happened.
As a last remark, a variable like public static boolean m_stopped that you share between two threads must be declared volatile to ensure that a thread will notice modifications made by another thread. It happens to work here without, because the JVM’s optimizer did not do much work for such a short running program and architectures like x68 synchronize caches. But it’s unreliable.
I am trying to find out whether it is possible to create Java dynamic proxy to automatically close Autocloseable resources without having to remember of embedding such resources with try-resources block.
For example I have a JedisPool that has a getResource method which can be used like that:
try(Jedis jedis = jedisPool.getResource() {
// use jedis client
}
For now I did something like that:
class JedisProxy implements InvocationHandler {
private final JedisPool pool;
public JedisProxy(JedisPool pool) {
this.pool = pool;
}
public static JedisCommands newInstance(Pool<Jedis> pool) {
return (JedisCommands) java.lang.reflect.Proxy.newProxyInstance(
JedisCommands.class.getClassLoader(),
new Class[] { JedisCommands.class },
new JedisProxy(pool));
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Jedis client = pool.getResource()) {
return method.invoke(client, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw e;
}
}
}
Now each time when I call method on Jedis (JedisCommands) this method is passed to proxy which gets a new client from the pool, executes method and returns this resource to the pool.
It works fine, but when I want to execute multiple methods on client, then for each method resource is taken from pool and returned again (it might be time consuming). Do you have any idea how to improve that?
You would end up with your own "transaction manager" in which you normally would return the object to the pool immediately, but if you had started a "transaction" the object wouldn't be returned to the pool until you've "committed" the "transaction".
Suddenly your problem with using try-with-resources turns into an actual problem due to the use of a hand-crafted custom mechanism.
Using try with resources pros:
Language built-in feature
Allows you to attach a catch block, and the resources are still released
Simple, consistent syntax, so that even if a developer weren't familiar with it, he would see all the Jedis code surrounded by it and (hopefully) think "So this must be the correct way to use this"
Cons:
You need to remember to use it
Your suggestion pros (You can tell me if I forget anything):
Automatic closing even if the developer doesn't close the resource, preventing a resource leak
Cons:
Extra code always means extra places to find bugs in
If you don't create a "transaction" mechanism, you may suffer from a performance hit (I'm not familiar with [jr]edis or your project, so I can't say whether it's really an issue or not)
If you do create it, you'll have even more extra code which is prone to bugs
Syntax is no longer simple, and will be confusing to anyone coming to the project
Exception handling becomes more complicated
You'll be making all your proxy-calls through reflection (a minor issue, but hey, it's my list ;)
Possibly more, depending on what the final implementation will be
If you think I'm not making valid points, please tell me. Otherwise my assertion will remain "you have a 'solution' looking for a problem".
I don’t think that this is going into the right direction. After all, developers should get used to handle resources correctly and IDEs/compilers are able to issue warnings when autoclosable resources aren’t handled using try(…){}…
However, the task of creating a proxy for decorating all invocations and the addition of a way to decorate a batch of multiple action as a whole, is of a general nature, therefore, it has a general solution:
class JedisProxy implements InvocationHandler {
private final JedisPool pool;
public JedisProxy(JedisPool pool) {
this.pool = pool;
}
public static JedisCommands newInstance(Pool<Jedis> pool) {
return (JedisCommands) java.lang.reflect.Proxy.newProxyInstance(
JedisCommands.class.getClassLoader(),
new Class[] { JedisCommands.class },
new JedisProxy(pool));
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Jedis client = pool.getResource()) {
return method.invoke(client, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
public static void executeBatch(JedisCommands c, Consumer<JedisCommands> action) {
InvocationHandler ih = Proxy.getInvocationHandler(c);
if(!(ih instanceof JedisProxy))
throw new IllegalArgumentException();
try(JedisCommands actual=((JedisProxy)ih).pool.getResource()) {
action.accept(actual);
}
}
public static <R> R executeBatch(JedisCommands c, Function<JedisCommands,R> action){
InvocationHandler ih = Proxy.getInvocationHandler(c);
if(!(ih instanceof JedisProxy))
throw new IllegalArgumentException();
try(JedisCommands actual=((JedisProxy)ih).pool.getResource()) {
return action.apply(actual);
}
}
}
Note that the type conversion of a Pool<Jedis> to a JedisPool looked suspicious to me but I didn’t change anything in that code as I don’t have these classes to verify it.
Now you can use it like
JedisCommands c=JedisProxy.newInstance(pool);
c.someAction();// aquire-someaction-close
JedisProxy.executeBatch(c, jedi-> {
jedi.someAction();
jedi.anotherAction();
}); // aquire-someaction-anotherAction-close
ResultType foo = JedisProxy.executeBatch(c, jedi-> {
jedi.someAction();
return jedi.someActionReturningValue(…);
}); // aquire-someaction-someActionReturningValue-close-return the value
The batch execution requires the instance to be a proxy, otherwise an exception is thrown as it’s clear that this method cannot guarantee a particular behavior for an unknown instance with an unknown life cycle.
Also, developers now have to be aware of the proxy and the batch execution feature just like they have to be aware of resources and the try(…){} statement when not using a proxy. On the other hand, if they aren’t, they lose performance when invoking multiple methods on a proxy without using the batch method, whereas they let resources leak when invoking multiple methods without try(…){}on an actual, non-proxy resource…
I have code (simplified) like this:
class A {
B b = new B();
void close() {
b.close();
}
}
class B {
Closeable mustBeClosed = new Closeable() {
{
System.out.println("create");
}
#Override
public void close() {
System.out.println("close");
}
};
int n = 0 / 0;
void close() {
mustBeClosed.close();
}
}
//code
try (A a = new A()) {
//do something
}
How to guarantee mustBeClosed is released?
This likely happens when the object hierarchy is complex. Override finalize for B might not be a perfect solution.
Any best practice or principle against this issue?
A revised version looks like:
class B {
Closeable mustBeClosed;
B() {
try {
mustBeClosed = ...
//other initialization which might raise exceptions
} catch (throwable t) {
close();
throw t;
}
}
void close() {
if (mustBeClosed != null) {
try {
mustBeClosed.close();
} catch (Throwable t) {
}
}
//all other resources that should be closed
}
}
However this takes too much code and is far from elegant. What's more, it seems that all classes in the ownership hierarchy should follow the same style, which results lots of code.
Any advice?
Your problem is that try-with-resources won't (actually can't) call close() if the constructor throws an exception.
Any object construction that allocates a resource, and has the potential to fail during construction after the resource is allocated, must release that resource before the exception is cascaded up the call stack.
Two ways to fix that:
1) Make sure the resource allocation is the last action performed. In your case, that means move field n up before field mustBeClosed.
2) Handle the resource construction in the constructor, not in a field initializer, so you can catch any subsequent exception and release the resource again before re-throwing the exception, as your alternate solution shows.
However, you don't have to null-check in the close() method, because mustBeClosed will always be non-null if the object construction succeeds, and close() cannot be called if the object construction fails.
Use a wrapper method to close all Closeable instances gracefully.
closeGraceFully(Closeable c) { // call this guy for all instances of closeable
try{
c.close();
} catch(IOException ex) {
// nothing can be done here, frankly.
}
}
Then call this wrapper method. don't call close() directly. Don't use finalizers they are evil and will slow down your app.