2
donuts
3y

In Java or any object oriented languages.

I have a complex object (X) made up of other objects, some of which open network connections that remain open.

Now there's a function that needs to create a new X every time it's called but didn't need it after it returns... but X isn't destroyed because those connections are still open.

Is there a way to destroy X without needing to explicitly close all the connections?

Also wondering, if I close the program itself, all resources are freed by the OS. How does the OS do it?

Comments
  • 6
    The feature you're looking for is Try with resource.

    For longer lived resources, you'll want a manager, factory or facade that handles Closeable on the classes they manage/produce/wrap.

    https://docs.oracle.com/javase/8/...

    The operating system doesn't guarantee that killing a process closes all connections, that handled on a protocol, thread and I/O feature basis. Connections will eventually time out and become nonresponsive, and sometimes processew will leave a port bound even if they don't exist anymore.

    MOTS: always clean your shit up
  • 1
    @SortOfTested so as long as I wrap X with try {}, it would close all the connection?
    or do I need to have X implement Closable and in close() explicitly close the connections created by the inner objects?
  • 1
    In c# couldn't you use a "using" statement for this?

    (you did say other oops)

    No idea if java has similar, is this what the try can do in java?
  • 0
    @nibor only if the object is explicitly disposable, which might be... weird in a lot of cases
  • 1
    @hubiruchi true, but less weird for network resources, which really should be handled by disposable objects
  • 0
    @hubiruchi so still need to dispose of it explicitly.

    Not like INotifyPropertyChanged where WPF does some backend binding magic that refreshed the UI whenever it's called in the setters? Though I guess that counts as explicit as well...
  • 0
    @donuts my problem with this is not the need for manually disposing the instance, but making interfaces that have zero reasons to be dispoable disposable
  • 1
    @donuts
    Try with resources is C# using for java.

    https://docs.oracle.com/javase/...

    It's for when you want to bind object lifetime to connection lifetime and have cleanup handled when the socket/IO terminates. Autocloseable and Closeable are IDisposable for Java.

    If you want to invert that relationship, look at thing Guava ServiceManager.

    https://guava.dev/releases/19.0/...

    Re: WPF

    I would typically handle most of my binding via inheriting MarkupExtension. Directly handling INotifyPropertyChanged gets messy and boilerplatey pretty quick. XAML already has enough boilerplate 🤣
  • 0
    @SortOfTested yes but actually in BufferedReader source code I see in close() it explicitly closes the stream.

    So in my case, in the parent implementing Closable, the close method still would need to call close() on each of it's children explicitly?
  • 0
    @SortOfTested For Service manager it looks like it is assuming there's a global object there's reused by all other classes?

    In my case each request (http server app) created it's own copy of a Service for it's own use. (Probably bad design but I have no say in who gets hired or time to review other people's work... Until it causes a prod issue that no one else knows how to fix...)

    It turns out now though when the Request finishes, the copy and it's connections remain open whereas it should be disposed completely/GCd.

    So I guess with try with resources, I want to explicitly say this object is no longer used and all its resources including connections should be closed, freed.
  • 0
    Explicit cleanups are better IMO.
  • 2
    @SortOfTested how are you so god damn competent?
  • 1
    @donuts
    If you want more than abstract options, you're going to need to give us more concrete code.
  • 0
    @SortOfTested so this is the general structure we have and I add the implements Closable and try {}. (I'm typing on phone...)

    class Service implements Closable {
    private SomeClient conn = new ...;
    public Service() {
    conn.open();
    }

    Public close(){
    //Leave blank or need to explicitly call conn.close(), what if there isn't one or it doesn't work?

    //This is from my point of view a external lib so cannot edit the code and don't know what exactly close does either
    }

    public Response getData() {
    return conn.getData();
    }
    }
  • 0
    class Server {
    @Get
    public Response doSomething() {
    try (Service x = new ...) {
    return x.getData();
    }
    }
    }

    What's happening before (without the Closable stuff), was everytime some one calls doSomething(), the created object and it's stays in memory and conn stays open.

    How can I just say once I exit doSomething(), get rid of the object, it's children and close all the connections?

    If I kill the program it closes all of them but can I do it without killing the program?
  • 0
    @SortOfTested I guess it's fine, can just trial and error the rest but need to deploy to our Linux server to test.

    Somehow can't run the program properly on local... takes 30mins to build n deploy though....

    Previous dev didn't leave any docs....
    Maybe I'll do the same when I leave... Can't imagine the shitstorm that would result... ¯\_(ツ)_/¯
Add Comment