jdk versus openjdk - Optimierung von Konstanten?

Sn0wm4n

Mitglied
Hallo zusammen,

im Folgenden zeige ich Euch den Quelltext zu einem Mini-Programm, das mir ziemlich rätselhaft vorkommt:
Java:
public class InfiniteLoop {

	public static final int END = Integer.MAX_VALUE;
	public static final int START = END - 100;
	
	public static void main (String[] args) {
		
		int count = 0;
		for (int i = START; i <= END; i++) {
			count++;
		}
		
		System.out.println(count);
	}
}

Kurze Erklärung des Source:
Im Prinzip wird einfach eine Schleife von START bis END durchlaufen und sodann die Anzahl der Durchläufe ausgegeben - im Allgemeinen kein Problem.
Da nun aber END auf den maximal möglichen Wert eines 4Byte signed Integer gesetzt wird und die Schleife erst bei i > END abbricht (da i <= END), kommt es zu einer Endlos-Schleife. Völlig korrekt - der Integer i muss theoretisch im "letzten" Schleifendurchlauf um 1 größer als der maximal mögliche Integer sein, was nicht möglich ist. Stattdessen wird i klammheimlich umgebogen auf Integer.MIN_VALUE. Daher wird die Schleife nie beendet.
So auch das von mir erwartete Ergebnis.

Das Problem:
Ich habe die Start- und Endwerte explizit als Konstanten deklariert, auch wenn das eigentlich nicht nötig wäre, um eine Endlosschleife zu erzeugen.
Mit jre6 wie auch mit java-6-openjdk als Standard-VM funktioniert das Programm auch wie erwartet (Endlosschleife).
Aaaber: Nun entferne ich den final-Modifizierer von END. Dadurch sollte logischer Weise (nach meiner Logik :D) das Ergebnis nicht verändert werden. Für die sun/oracle-Variante stimmt das auch. Unter Verwendung der freien Variante wird nun jedoch die Zahl "101" ausgegeben - die Schleife terminiert also anscheinend.

Warum genau nun via openjdk die Schleife terminiert ist mir ein Rätsel. Irgendwas muss intern anders laufen, sobald ich den final-Modifizierer entferne. Allerdings sollte das nach meinem Verständnis keine Auswirkung haben; die Zählvariable i bleibt ja trotzdem gleich.

Daraufhin habe ich mir Interesse halber den Bytecode der beiden Quelltexte via javap "disassembled". Die Ausgaben habe ich als txt-Datei diesem Thread angehängt. Aber auch da sehe ich nichts, was die Ursache der Änderung sein könnte.

Die eigentliche Frage:
Hat von Euch einer eine Ahnung oder Vermutung, was hier im openjdk anders behandelt wird (wenn das überhaupt die Ursache ist), sodass obiges Problem auftritt (evtl. irgendeine Art von automatischer "Optimierung")?
Theoretisch wäre das Problem gar nicht mal so wichtig, da es sich um einen reinen corner-case handelt und man in solchen Randfällen sicher keine Integer-Zählvariable nutzen würde. Aber trotzdem interessiert es mich einfach, warum die verschiedenen VMs in diesem Punkt völlig anders reagieren.
Entweder sehe ich vor lauter Bäumen den Wald nicht mehr oder es ist wirklich ein sehr komisches Problem.


Mein System:
Es sollte eigentlich dabei weniger eine Rolle spielen, aber der Vollständigkeit halber:

System mit openjdk
  • 32-bit Unix (Ubuntu 10.04)
  • Eclipse 1.2.2.x zur Entwicklung

Referenz-System ohne openjdk
  • 64-bit Windows (Win7)
  • Eclipse 1.2.2.x zur Entwicklung

Falls ich noch etwas vergessen habe, einfach melden.

Vielen Dank im Voraus, dass Ihr schonmal bis hier hin gelesen habt. ;)
Und noch ein größeres Dankeschön für Hilfe!

viele Grüße,
Sn0wm4n
 

Anhänge

  • infinite_loop.txt
    732 Bytes · Aufrufe: 8
  • terminating_loop.txt
    948 Bytes · Aufrufe: 7

Empire Phoenix

Top Contributor
Ich tippe auf ne optimierung (inner jvm) die bemerkt das du die schleife 101 mal ausführst ( wenn es keine integergrenze gäbe)
also packt die das ganze zum optmieren einfach 101 ma hinterinander, und optimiert dann wahrschenlich die 101 count ++ zu einem count = 101 um.

Effektiv ist das also ein Bugfeature, da die optimierung nicht prüft, ob die 101 mal über haupt mit dem Werteberech möglich sind.
 

Sn0wm4n

Mitglied
Hallo Empire Phoenix,

danke für die schnelle Antwort.
Dann werde ich mal nach genauen Spezifikationen zu den Optimierungen beider jvm suchen (interessiert mich noch, wo / wie / wann genau das Programm "kaputt optimiert" wird^^) und mich evtl damit direkt an die openjdk'ler wenden.

viele Grüße,
Sn0wm4n
 

Sn0wm4n

Mitglied
Spannend wäre jetzt: Was passiert, wenn in der Schleife noch ein System.out.println(count) steht...

Ups, ganz vergessen, src. Das Verhalten hatte ich auch schon getestet.
Sobald ich via openjdk das final entferne und ein belibiges SysOut in der Schleife einfüge, terminiert diese wieder nicht.

Hast Du eine Ahnung, warum dies so ist?
 

Marco13

Top Contributor
Das würde die Vermutung von Empire Phoenix unterstützen: Er erkennt, dass dort effektiv nichts anderes gemacht wird als 100 mal count++, und rechnet das Ergebnis direkt aus... Man könnte noch ein bißchen rumprobieren, und mal versuchen, ihn mit dem Hochzählen eines long-Wertes länger zu beschäftigen. Wenn das JDK dann z.B. 5 Sekunden braucht, um von 0 bis Long.MAX_VALUE zu zählen, und das OpenJDK es in 0.00001 Sekunden schafft, kann man sicher sein, dass es NICHT wirklich gezählt hat... ;)
 

Sn0wm4n

Mitglied
So schlau ist open-jdk anscheinend nicht :)
Meine Schleife von 0 bis zum max. Long-Wert läuft nun schon mehrere Minuten - wird (ohne sysout) wohl nicht optimiert.
Ich werde - voraussichtlich am Wochenende - noch ein wenig herumtesten, unter welchen Bedinungen optimiert wird. Für heute (naja, mittlerweile ists ja schon nach Mitternacht) reicht es erstmal *g

viele Grüße und Danke für die Antworten,
Stefan
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
P Versioniering 4 Segments versus 3 Segments + 1 only if needed Allgemeine Java-Themen 3
T Exception versus Rückgabeparamter Allgemeine Java-Themen 26
G Thread- save versus Nicht- Thread- save Allgemeine Java-Themen 2
R Timing-Problem (?) Linux versus Windows Allgemeine Java-Themen 13
Ark O-Notation und Zahl versus String-Repräsentation Allgemeine Java-Themen 7
KonradN Oracle übergibt (Java Teile der) GraalVM Community Edition an OpenJDK Community Allgemeine Java-Themen 2
P JDK installieren OpenJDK: Lizenz von mit JLINK erzeugten Executables Allgemeine Java-Themen 1
M Openjdk - gibt es auch eine Openjre? Allgemeine Java-Themen 7
D Vergleich OracleJDK/OpenJDK Allgemeine Java-Themen 7
R JDK installieren OpenJDK-Aufruf sehr langsam Allgemeine Java-Themen 4
R JDK installieren OpenJDK druckt falsch Allgemeine Java-Themen 3
Blender3D Linzensen OpenJDK ist die kommerzielle Nutzung kostenfrei? Allgemeine Java-Themen 3
M OpenJDK Allgemeine Java-Themen 1
G UnterSchied OpenJDK vs JDK Allgemeine Java-Themen 11
C Darstellungsproblem unter Debian und OpenJDK Allgemeine Java-Themen 5
C OpenJDK - FileReader throws FileNotFoundException Allgemeine Java-Themen 19
C OpenJDK Allgemeine Java-Themen 4
M Optimierung einer Methode (byte-Geraffel) Allgemeine Java-Themen 2
L Best Practice Auslagerung von Code = Performance Optimierung? Allgemeine Java-Themen 4
F Zeit Optimierung - bzw. ms Optimierung Allgemeine Java-Themen 35
R Optimierung beim Vergleichen von 2 Bildern Allgemeine Java-Themen 23
HarleyDavidson Regex - Optimierung Allgemeine Java-Themen 4
K Optimierung kürzester Weg im Warenlager Allgemeine Java-Themen 8
O Algorithmus Optimierung Allgemeine Java-Themen 3
H Optimierung durch Threads Allgemeine Java-Themen 31
C Programmflow-Optimierung Allgemeine Java-Themen 7
G Klasse Optimierung Allgemeine Java-Themen 6
N Optimierung einer Berechnung Allgemeine Java-Themen 17
P Optimierung (&& ||) deaktivieren / umgehen? Allgemeine Java-Themen 9
G Optimierung StringBuilder Allgemeine Java-Themen 9
S Optimierung vom Laden von Grafiken Allgemeine Java-Themen 4
S Brainstorming --> Optimierung vonn Gefälleplatten Allgemeine Java-Themen 8
D Optimierung beim Casten Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben