4

I'm wondering if there is a good way of explicitly declaring (not necessarily enforcing) ownership transfer of resources in Java.

My problem is basically this: There are resources that need to be cleaned up (think AutoClosable) that are dependency-injected into an instance by its creator. I want to communicate to the creator that the instance takes full ownership over, and responsibility for, said resource (at source level, since I am pretty sure there is no way to enforce that in Java).

I am currently entertaining the idea of using a wrapper class Owned<T>, that basically behaves like an Optional that always needs to be filled.

Is this worthwhile? Should I just put a comment in the JavaDoc? Or is there a common way this is handled?

  • It's not possible in Java. And I think it's a bad practice to pass around AutoCloseable resources for 2 reasons: 1) if you don't create the resource you don't know if it's already open and/or if you have to close it. 2) you introduce side-effects in your program making it less testable. That's why I never pass such resources around. My golden rule is: create it, use it, throw it. If you have some code showing this scenario (where you inject an AutoCloseable) I'll be glad to help you refactor it this way. – Spotted Sep 23 '16 at 12:44
  • I'll admit it's not optimal, but injecting those resources makes it easier to test among other things. I have some pretty specific loggers for example, and they need some configuration before use. Putting the burden of knowing how to configure those onto every user of the logger does not make much sense to me. C++ really spoiled me with having control over these things... – Kolja Sep 24 '16 at 10:59
  • Some why not passing only the configuration (in the logger case) as dependency ? – Spotted Sep 26 '16 at 12:47
  • This would be a great thing to put right into the language definition instead of just having an annotation, and my hunch is that enforcing declared ownership would not even be too difficult for the compiler. (Just dreaming :-) – Harald Jan 28 '17 at 6:41
5

I think it should be possible to implement this using @Owned annotations for function parameters and return types. Whoever calls new initially owns a resource. If you own a resource, you must either destroy it or give it away – either by returning it as an @Owned resource or passing it to a function that claims ownership of it. After you've given up ownership, you must not use the resource any more. If you got passed a resource as a parameter not annotated as @Owned, you must not destroy it and must not pass it to functions that would claim ownership of it. To define “destruction”, we'd probably want a @Destroys annotation for methods on a resource.

The idea is basically taken from Rust (disclaimer: I have never actually programmed in Rust) which itself I believe is strongly inspired by C++. I think that the annotation system in Java should be strong enough to hook in a static analyzer that would enforce the correctness of your program with zero run-time overhead. Since I have never written a static analyzer plugin for the Java compiler, I have no idea how difficult / easy that would be. A more practical problem you'd have to overcome is that many standard and third-party library functions will not care about your annotations and you'd need to figure out some mechanism to inform your analyzer that you know what you are doing. (Such as “unsafe” @Owned T makeOwned(T t) and T makeNotOwned(@Owned T t) methods that “cast away” the annotation. Or support for an external annotations file to load annotations for third-party intrefaces from.)

I think that this would be a very interesting academic project but fear that it would almost certainly turn into a giant time sink if applied to any practical project.

  • 1
    +1. I note that if you can define simple rules for how your annotations should be used, you can probably implement a detector for findbugs that would identified violations of them. At the very least, I suspect you would require that any object that has an @Owned field would implement AutoCloseable or some similar alternative and call the close method of the field in its own close method. You would also require that @Owned variables not be passed anyway or stored that isn't also annotated @Owned. Those two rules alone would probably catch a large proportion of mistakes. – Periata Breatta Sep 23 '16 at 4:42
  • Had not thought of an annotation, that's a good idea. It might also be the least intrusive way of doing this. I guess I will also look into extending findbugs. Thanks! – Kolja Sep 24 '16 at 11:01
2

I am not sure there is a common way this is handled, because it takes a lot of work and discipline to do it right, and most people would rather leave open the possibility of error than discipline themselves.

I like to experiment, especially with ways of reducing the possibility of error, so from time to time I have been using various techniques.

One technique is the "hand-off" pattern: whenever a closeable resource is passed from object A to object B, a "handOff" boolean flag is also passed, telling object B whether it should dispose of the resource when it is done with it. I am not terribly satisfied with it, because it is not enforceable at all: the holder of the resource may do the exact opposite of what the "handOff" parameter suggests.

Another technique which is halfway enforceable is using the type system to its fullest extent: if you are given a disposable resource, you must always dispose it. If you are not going to dispose it, then it should not be disposable. In other words, if it is not disposable, then you cannot dispose it.

Unfortunately, the JRE has not been designed with this in mind, so you have to redo a lot of classes and interfaces for it to work. For example, InputStream is a class which implements Closeable. So, if you were to use the type system technique with this class as it is, it would mean that whenever you would pass an InputStream to someone you would have to kiss it bye-bye.

So, classes like InputStream would have to be reworked as follows:

An InputStreamResource class is introduced, fully encapsulating the original InputStream class of the JRE; A new InputStream interface is introduced, containing all the methods of the original InputStream class, except Close(); then, InputStreamResource is made to implement the new InputStream interface, and the Closeable interface. Thus, anyone accepting an InputStreamResource promises to close it, while anyone accepting an InputStream interface is simply unable to close it, because it is not Closeable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.