Resource leak - switch

hallo,

new Formatter(), was ich eh durch String.format() ersetzen werde, wird in Eclipse Juno (edit: äh, ich meine Luna) als Closable angemeckert,
in einem switch aber keine Meldung, auch nicht in ernsteren Fällen wie als Beispiel FileReader

bei anderen auch?, gibts Erklärung?

        new FileReader(""); // Resource leak: '<unassigned Closeable value>' is never closed
        switch (0) {
            case 0:
                new FileReader(""); // ok?
        }
        if (true) {
            new FileReader(""); // Resource leak: '<unassigned Closeable value>' is never closed
        }
    }

Hallo,

Ich bin auch etwas verwundert. In den Einstellungen zu Warning/Errors gibt es 2 Punkte:

Resource leak: warning
Potential resource leak: ignore

aber selbst wenn man den 2. Punkt auf “warning” setzt wird das ignoriert. Ich würde sagen, dass es ein Bug in Eclipse ist.

Gleiches Problem in Mars mit jdk 1.8.
Du könntest unter bugs.eclipse.org einen Bug dazu aufmachen, Komponente müsste entweder JDT-Core oder JDT-UI sein.

ich hab keine Lust auf Bug-Meldung mit evtl. Anmeldung usw.,
falls wer drin ist oder sich sonstwie berufen fühlt und es nicht noch Erklärungen gibt, bitte

Naja, dass es nie geschlossen wird ist falsch (in einer typischerweise länger laufenden App), aber bei kurzzeitig laufenden, bzw niemals genug Müll produzierenden App kann das durch aus passieren. Die Finalizer sind lauf Spec nicht erzwungen ausgeführt zu werden.

Was passiert denn bei if-else?

So wie es aussieht, wird bei switch und if-else jeweils nur das Erste angemeckert. Hinter “if(true)” wird definitiv abgearbeitet. “if(true)” wird wohl von JIT auch wegoptimiert.

		FileReader fra, frb;
		int i = new Random().nextInt();
		int j = new Random().nextInt();
		switch(i) {
		case 0:
			fra = new FileReader("0"); // Resourceleak
			break;
		default:
			fra = new FileReader("1"); // kein Resourceleak
			break;
		}
		if(j == 0) {
			frb = new FileReader("0"); // Resourceleak
		} else {
			frb = new FileReader("1"); // kein Resourceleak
		}
	}```
Angemeckert werden offensichtlich nur die ersten gefundenen möglichen und sichere also unbedingt auftretende Resourceleaks.

läßt man das Default weg sollte der 0-Fall weiterhin kritisch sein, aber dann keine Warnung mehr,

2x komplett ohne Warnung:

        FileReader frb = null;
        int i = new Random().nextInt();
        switch (i)      {
            case 0:
                fra = new FileReader("0"); // kein Resourceleak
                break;
            default:
                frb = new FileReader("1"); // kein Resourceleak
                break;
        }
        fra.read();
        frb.read();
        FileReader frb = null;
        int i = new Random().nextInt();
        if (i == 0)    {
            fra = new FileReader("0"); // kein Resourceleak
        }   else     {
            frb = new FileReader("1"); // kein Resourceleak
        }
        fra.read();
        frb.read();

ein sinnvolles System ist dahinter sicher nicht zu erkennen

und zwar nur dann wenn ein zweites Setzen auf dieselbe Variable folgt, dann zumindest etwas Nachschauen, was zwischenzeitlich passierte

(edit 11:00: ein Kreuz mit den vielen Versionen, die beiden Beispiele in diesem Posting nur unter Eclipse Juno, Java 7 ein Problem - in Eclipse Luna, Java 8, gut bemeckert)

*** Edit *** (11:00)

zuvor nicht ganz aktuelle Beispiele, nun wieder nach neuesten Stand:

        InputStream in = null;

        if (Math.random() < 0.5)   {
            in = new FileInputStream("");
        }
//        else   {
//            FileInputStream fin = new FileInputStream("");
//            in = fin;
//        }

        in = new FileInputStream("");
        return in;
    }

ist in dieser Form ohne Warnung, auch wenn in mindestens einmal vor Schließen überschrieben wird,

das Auskommentierte dazu → sowohl im if als auch else eine Warnung…

möglicherweise relevant:

https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html

An object that may hold resources (such as file or socket handles) until it is closed. The close() method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header. This construction ensures prompt release, avoiding resource exhaustion exceptions and errors that may otherwise occur.

ist die Frage wie sich das auf den Methodenaufrufer fortsetzt - wenn deine test() in einem try-catch aufgerufen wird, sollte es ja überhaupt keine Probleme geben - zumindest beim Aufruf mit „Ressourcen“

sieht aber eher nach einem bug aus, langsam wird die Flußanalyse durch Compiler und IDE immer komplizierter :slight_smile:

Der wichtige Unterschied ist, da ist kein try-with-resource!

als Ergänzung zu @Noctarius try-with-ressource sieht so aus.

  in.read();
} catch (Exception e) {
  e.printStackTrace();
}```

"in" ist nur im Body des try-catch-Blocks gültig und das close() wird automatisch, incl. dem Fangen dabei auftretender Exceptions, beim verlassen des try-catch-Blocks aufgerufen.

Ein sehr schönes Sprachfeature.

schon, hat aber - soweit Google das beurteilen kann - mit der von SlaterB gefundenen Anomalie leider nichts zu tun.

Kann man drehen und wenden wie man will, ich glaube da ist ein echter Bug in Eclipse.