Math.sin(double) ist eine native Implementierung, aber wie hier genau optimiert wird, kommt auf die JVM-Implementierung an. Trigonometrische Berechnungen sind echt ein Problem, insbesondere, weil sie alle strictfp durchgeführt werden (siehe Quellcode). Die Berechnung ist zwar native doch muss der Fließkommaprozessor mitunter den IEEE 754 Standard nachbilden, um auf ein exaktes reproduzierbares (eben strictfp) Ergebnis zu kommen auf allen Rechnern zu kommen. Eine oft diskutierte Lösung ist eine native C-Funktion zu nutzen, die direkt SIN vom Fließkommaprozessor nutzt, ohne die in IEEE 754 beschriebene Lösung zu berechnen. (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5005861) Das Problem ist in Java 6 angegangen worden aber nicht abschließend gelöst. Vielleicht gehen auch Sin-Tabellen, aber dass muss man dann ganz genau messen, ob sich das lohnt.
Q&A: Wie kann man die Netzwerkübertragung besser optimieren?
Bei der Client-Server-Kommunikation meines Spiels harkt es und das auch nur bei einem Spieler, was kann man tun?
Es gibt kaum Möglichkeiten zur Optimierung im Java-Umfeld. Die Netzwerkverbindung sollte auf bleiben, sodass keine (große) Zeit für den Neuaufbau anfällt. Serialisierung ist nicht so teuer, GZippen wird auch nicht viel bringen. Im lokalen Netz ist time(UDP) = time(TCP) und bei UDP muss man zu viel selbst machen, da bringt auch ein Protokollwechsel im Grunde nichts. NIO wäre mit Kanonen auf Spatzen und lohnt sich nur bei vielen Verbindungen. Eventuell bringt Nagle noch was: http://www.davidreilly.com/java/java_network_programming/#3.3.
Thema der Woche: Collections-Update in Java 7
- Lies http://docs.oracle.com/javase/7/docs/technotes/guides/collections/changes7.html.
- Wie gliedert sich
TransferQueue
undBlockingQueue ein, welche Änderungen an der Typ-Hierarchie gibt es genau? - Was genau ist mit Änderungen am Hashing gemeint? Ist Hashing nun langsamer als vorher? Spielt die eigene Hash-Funktion keine bedeutende Rolle mehr? Werden Attacken wie http://stackoverflow.com/questions/8669946/application-vulnerability-due-to-non-random-hash-functions verhindert?
Transformation von Java nach C# (Java2Cs Translator)
ILOG ist ein Teil von IBM und hat für ein Projekt einen Übersetzer von Java nach C# entwickelt und bei SourceForge gehostet. Eingebunden ist es über Eclipse und dann macht man einfach nur ein File > Export > Other > ILOG Java to CSharp Translator. Es unterstützt alle Java 5 Features wie Generics, Enums, foreach, aber nicht Java 7. Ein paar Dinge können natürlich nicht übertragen werden und auch natürlich wird nicht alles von den Java-Bibliotheken übertragen. Seit einiger Zeit gab es kein Update mehr beim Projekt.
JOpenDocument API
Zum Zugriff auf Dokumente und Spreadsheets von OpenOffice (for OASIS Open Document ) ist JOpenDocument (http://www.jopendocument.org/) eine GPL-Bibliothek, die das mit einer einfachen API unterstützt.
Etwa das Laden und Verändern von Spreadsheets:
File file = new File( "c:/in.ods" );
SpreadSheet createFromFile = SpreadSheet.createFromFile( file );
Sheet sheet = createFromFile.getSheet( 0 );
sheet.setValueAt( "Filling test", 1, 1 );
sheet.getCellAt( "A1" ).setValue( "On site support" );
sheet.getCellAt( "I10" ).setValue( new Date() );
sheet.getCellAt( "F24" ).setValue( 3 );
File outputFile = new File( "c:/out.ods" );
sheet.getSpreadSheet().saveAs( outputFile );
Weitere Beispiele gibt http://www.jopendocument.org/documentation.html.
Interessant ein ein purer Java-Viewer, und damit die Möglichkeit in PDF zu exportieren, ohne dass man OO dazu fernsteuern muss.
Beim Testen der SpreadSheet-API sind mir leider einige Nachteile aufgefallen:
- Es gibt keine Named References
- Die API ist sehr Datei-orientiert. Nur im Speicher Dokumente anzulesen und zu verarbeiten ist nicht möglich. Ich sehe erst einmal keine Methode, wie ein Servlet z.B. sich den InputStream auf ein OO-Dokuments holen und als OutputStream an den Client verschicken kann, ohne dass man vorher das OO-Dokument in eine Datei schreibt.
- Soll der eingebauter Viewer verwendet werden, können TIFF-Bilder nicht angezeigt werden.
- GPL könnte für einige Bereiche ein Problem sein. Es werden aber kommerzielle Lizenzen verkauft.
- Nur das Anzeigen von einfachen Dokumenten ist möglich.
Community-Aufruf: Testet eure Software mit Java 8
Das OpenJDK 8-Team spielt gerade das Release mit unterschiedlichen OS-Produkten durch, um Inkompatibilitäten festzustellen. Bitte testet eure Software mit aktuellen Builds von Java 8 und meldet Fehler, etwa hier im Blog oder noch besser auf https://groups.google.com/forum/#!forum/adopt-openjdk. Falls eure Software über ein CI-System bebaut und getestet wird, nehmt Java 8 jetzt schon mit auf.
Die aktuelle Matrix gibt es hier: https://java.net/projects/adoptopenjdk/pages/TestingJava8. Man sieht, dass die wichtigen Projekte, wie GlassFish/Groovvy noch nicht funktionieren.
Project |
Open Issue(s)? |
Closed Issue(s)? |
Testing Status |
Adopt OpenJDK Volunteer |
Project Contact Details |
Manual |
Greg Bakos |
||||
None |
|||||
Unknown |
|||||
Manual |
Helio Frota |
||||
Prototype phase |
Manual |
Yosi Pramajaya |
|||
Manual |
Mani Sarkar |
||||
Test failed under Java 8 (race condition) |
Martijn Verburg |
||||
Manual |
Greg Bakos |
||||
CI |
|||||
Manual |
Mani Sarkar |
||||
See UISpec4j |
Manual |
Helio Frota |
Quick Subscribe using dev team |
||
Manual |
Helio Frota |
||||
Manual |
Mani Sarkar |
||||
Helio Frota |
|||||
CI |
Trisha Gee |
||||
MutabilityDetector |
All three projects support Java 8 |
Manual |
Graham Allan |
||
See Scala |
Manual |
Helio Frota |
|||
Manual |
Mani Sarkar |
||||
build does not support JDK 8 yet |
Manual |
Helio Frota |
|||
Manual |
Mani Sarkar |
||||
Helio Frota |
|||||
CI |
Hildeberto |
||||
Manual |
Andres Almiray |
||||
Manual |
Andres Almiray |
Thema der Woche: Werte und Operatoren erkennen
- Lies Reguläre Ausdrücke, Pattern.matches() bzw. String#matches(), Die Klassen Pattern und Matcher und Finden und nicht matchen.
- Schreibe in Programm mit regulären Ausdrücken, was in “hund 12 katze 59 maus 39” die Zahlen 12 59 39 ausgibt.
- Erweitere das Programm, dass auch Operatoren erkannt werden, wie “hund 33 + 12 x katze 3”, was ergibt 33 + 12 x 3.
- Erweitere das Programm um eine Methode double parseLine(String), was so eine Zeile wie “hund 33 + 12 x katze 3” bekommt, daraus Zahlen und Operatoren extrahiert, also “33 + 12 x 3” bildet, und das mit der JDK JavaScript Engine auswertet.
- Schaue das Video von http://www.acqualia.com/soulver/ und die Screenhots an.
- Implementiere damit http://www.acqualia.com/media/images/soulver/introduction/MeaningOfLife.png und aus dem Video die erste Berechnung von 00:00 – 00:08 mit einer Konsolenanwendung, und zeilenweiser Ausgabe, die einfach die Summe und das Zwischenergebnis in der die Spalte rechts auf der Konsole ausgibt.
- Optional: Man soll mit $? auf das letzte Ergebnis zugreifen können, mit $1, $2, … auf das 1. Zwischenergebnis, 2. Zwischenergebnis, usw.
- Implementiere damit http://www.acqualia.com/media/images/soulver/introduction/InterestRates.png.
Bean-Bean Mapping mit Dozer
Dozer ist eine kleine Open-Source Bibliothek (Apache-Lizenz) zum Mappen von JavaBeans auf JavaBeans. Motivationen gibt es genug — die Webseite zählt gleich einige Argumente auf:
- A mapping framework is useful in a layered architecture where you are creating layers of abstraction by encapsulating changes to particular data objects vs. propagating these objects to other layers (i.e. external service data objects, domain objects, data transfer objects, internal service data objects). A mapping framework is ideal for using within Assembler type classes that are responsible for mapping from one data object to another.
- For SOA/ESB systems, a side effect is the passing of domain objects between different systems. Typically, you won’t want internal domain objects exposed externally and won’t allow for external domain objects to bleed into your system.
- Mapping between data objects has been traditionally addressed by hand coding value object assemblers (or converters) that copy data between the objects. Most programmers will develop some sort of custom mapping framework and spend countless hours and thousands of lines of code mapping to and from their many transfer objects.
- A generic mapping framework solves these problems. Dozer is an open source mapping framework that is robust, generic, flexible, reusable, and configurable.
- Data object mapping is an important part of layered service oriented architectures. Pick and choose the layers you use mapping carefully. Do not go overboard as there is maintenance and performance costs associated with mapping data objects between layers.
Basis des Mappings sind XML-Dokumente; im einfachsten Fall:
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd">
<mapping>
<class-a>d.e.i.n.p.a.k.e.t.TestObject</class-a>
<class-b>d.e.i.n.p.a.k.e.t.TestObjectPrime</class-b>
<field> <A>yourSourceFieldName</A> <B>yourDestinationFieldName</B> </field>
</mapping>
</mappings>
Angestoßen wird er über ein Mapping-Objekt, welches auch leicht von Spring injiziert werden kann:
Mapper mapper = new DozerBeanMapper(); DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class);
oder
DestinationObject destObject = new DestinationObject(); mapper.map(sourceObject, destObject);
Interessant finde ich die JMX-Integration. Der Mapper gibt Statistik-Informationen etwa über die Anzahl gemappter Objekte.
Thema der Woche: N+1 SELECT Problem
Bei SQL-Anfragen über mehrere Tabellen trifft man schnell über das N+1 SELECT Problem.
- Finde mehr zu dem Problem und entwerfe ein Szenario, was das Problem deutlich macht.
- Welche Lösung gibt es für das Problem in SQL?
- Wie löst man das Problem in einer Anfragesprache wie JPAQL?
- Lässt sich das Problem durch geschickte Modellierung entschärfen? Warum ist das insbesondere für NoSQL-Datenbanken essenziell? Welchen Ansatz verfolgt man?
Java 7 auf Android? IntelliJ macht’s bis auf die Lib-Features fast möglich
Expression Language 3.0 (JSR-341), wow, aber komplett an mir vorbeigezogen
Schau http://www.youtube.com/watch?v=Uyx7fLXXSS4, http://www.youtube.com/watch?v=JEKpRjXL06w und http://rijkswatch.blogspot.de/2012/06/expression-language-30-is-in-public.html. Aus der Spezifikation http://download.oracle.com/otn-pub/jcp/el-3_0-fr-eval-spec/EL3.0.FR.pdf.
- Lambdas: fact = n -> n==0? 1: n*fact(n-1); fact(5) oder employees.where(e->e.firstName == ‘Bob’)
- Collection-Syntax: employees.where(e->e.firstName == ‘Bob’) oder {„one“:1, „two“:2, „three“:3}
- Streaming wie in Java 8: books.stream().filter(b->b.category == ‘history’) .map(b->b.title) .toList() oder [1,2,3,4,5].stream().substream(2,4).toArray()
Insgesamt:
■ Added Chapter 2 “Operations on Collection Objects”.
■ Added 1.8, String concatenation operator.
■ Added 1.13, Assignment operator.
■ Added 1.14, Semi-colon operator.
■ Added 1.20 Lambda Expression.
■ Added 1.22 Static Field and Methods.
■ Added T and cat to 1.17 Reserved words.
■ Modified 1.16 Operator precedence.
■ Modified coercion rule from nulls to non-primitive types.
■ Many changes to the javadoc API.
Schön ist, dass man das auch eigenständig außerhalb vom Web-Container verwenden kann. Das macht die EL interessant für Template-Lösungen.
Siehe auch YouTube Video: https://www.youtube.com/watch?v=JEKpRjXL06w
Überblick: Aktuelle Versionen der Java EE 7 Technologien
Von https://blogs.oracle.com/theaquarium/entry/java_ee_7_platform_completes:
JSRs:
- Java Platform, Enterprise Edition 7 (JSR 342)
- Concurrency Utilities for Java EE 1.0 (JSR 236)
- Java Persistence 2.1 (JSR 338)
- JAX-RS: The Java API for RESTful Web Services 2.0 (JSR 339)
- Java Servlet 3.1 (JSR 340)
- Expression Language 3.0 (JSR 341)
- Java Message Service 2.0 (JSR 343)
- JavaServer Faces 2.2 (JSR 344)
- Enterprise JavaBeans 3.2 (JSR 345)
- Contexts and Dependency Injection for Java EE 1.1 (JSR 346)
- Bean Validation 1.1 (JSR 349)
- Batch Applications for the Java Platform 1.0 (JSR 352)
- Java API for JSON Processing 1.0 (JSR 353)
- Java API for WebSocket 1.0 (JSR 356)
MRs:
- Web Services for Java EE 1.4 (JSR 109)
- Java Authorization Service Provider Contract for Containers 1.5 (JACC 1.5) (JSR 115)
- Java Authentication Service Provider Interface for Containers 1.1 (JASPIC 1.1) (JSR 196)
- JavaServer Pages 2.3 (JSR 245)
- Common Annotations for the Java Platform 1.2 (JSR 250)
- Interceptors 1.2 (JSR 318)
- Java EE Connector Architecture 1.7 (JSR 322)
- Java Transaction API 1.2 (JSR 907)
- JavaMail 1.5 (JSR 919)
MR steht für “Maintenance Releases”.
Kommandozeilenprogramm jcmd für Diagnosekommandos
Mit dem Kommandozeilenprogramm jcmd lassen sich Diagnosekommandos zu einer laufenden JVM schicken. Die Java-Programme werden wieder über eine PID identifiziert, die jcmd auch anzeigen kann:
$ jcmd.exe
2484 C:\Users\Christian\eclipse\\plugins/org.eclipse.equinox…
18868 sun.tools.jcmd.JCmd
Eclipse hat die PID 2484 und das Tool selbst – das bei jedem Starten natürlich eine neue PID bekommt – 18868.
Interessant wird jcmd dadurch, dass sich Diagnose-Kommandos senden lassen. Als erstes steht die PID, dann folgt das Kommando. Um ein Übersicht über die Häufigkeit von geladen Klassen zu bekommen ist GC.class_histogram zu nutzen:
$ jcmd.exe 2484 GC.class_histogram
2484:
num #instances #bytes class name
----------------------------------------------
1: 600676 40906520 [C
2: 549996 13199904 java.lang.String
3: 121570 4862800 java.util.WeakHashMap$Entry
4: 117120 3747840 java.lang.ref.WeakReference
5: 63926 2730616 [Ljava.lang.String;
…
Auf der Hilfeseite sind die Kommandos nicht aufgeführt, weil sie abhängig von der jeweiligen JVM sind und nicht im Tool jcmd selbst verankert sind. Daher müssen sie dynamisch von einem laufenden Java-Programm erfragt werden. Unser Elcipse-Prozess hatte die PID 2484, und dann kommt die Option help zum Einsatz:
$ jcmd.exe 2484 help
2484:
The following commands are available:
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help
For more information about a specific command use 'help <command>'.
Wie die letzte Zeile verrät, gibt ein angehängtes Kommando weitere Informationen, etwa
$ jcmd.exe 2484 help GC.heap_dump
2484:
GC.heap_dump
Generate a HPROF format dump of the Java heap.
Impact: High: Depends on Java heap size and content. Request a full GC unless th
e '-all' option is specified.
Permission: java.lang.management.ManagementPermission(monitor)
Syntax : GC.heap_dump [options] <filename>
Arguments:
filename : Name of the dump file (STRING, no default value)
Options: (options must be specified using the <key> or <key>=<value> syntax)
-all : [optional] Dump all objects, including unreachable objects (BOOLE
AN, false)
Was ist eine Oracle JDK/JRE Certified System Configuration?
Eine ideale, perfekt getestete und unterstützte Umgebung gilt als Oracle JDK/JRE Certified System Configuration. Das ist eine Kombination aus Betriebssystem mit installierte Service-Packs; das beschreibt das Unternehmen unter http://www.oracle.com/technetwork/java/javase/config-417990.html für Java 7. Bei gemeldete Bugs auf nicht zertifizierten Plattformen kann dann schnell ein „Sorry, das ist eine nicht-unterstützte Plattform, das schauen wir uns nicht weiter an“ folgen. Bei Linux ist zum Beispiel Ubuntu-Linux markiert als „Not certified on Oracle VM“. Das heißt nicht, dass es dort nicht zu 100% läuft, nur, dass im Fehlerfall eben kein Fix geben muss.
Java 8 Build 94 ist Feature-Complete
Daher wird jetzt nichts mehr neues reinkommen und die Entwicklung konzentrierst sich auf Bug-Fixes.
JavaScript, Rhino und Nashorn
Java ist zwar eine tolle Allround-Programmiersprache, aber die explizite Typisierung und der Zwang, Klassen und Methoden zu deklarieren, machen Java nicht wirklich attraktiv für Skripte, wo eher die Kompaktheit zählt und wo keine lang zu pflegenden Programme entstehen. Um die JVM und die Java-Bibliotheken auch zur Automatisierung von Abläufen einzusetzen, lässt sich neben der Java-Syntax auch alternative Programmiersprachen einsetzen.
JavaScript ist eine flexible interessante Programmiersprache, die mittlerweile auch außerhalb von Browsern populär ist, serverseitig eingesetzt wird und auch für die Entwicklung von Desktop-Anwendung – siehe Gnome 3, WinRT, Chrome Apps oder FirefoxOS.
Das Oracle JDK/OpenJDK bzw. das JRE[1] bringt ab Java 6 neben dem Java-Compiler eine JavaScript-Engine und ein Kommandozeilentool mit, das Sprite ausführt. So lässt sich JavaScript als alternative Programmiersprache einsetzen – die Sprache ist also auswechselbar und steht versinnbildlicht auf den Bibliotheken und der Laufzeitumgebung. Auch lässt sich die JavaScript-Umgebung in eigene Java-Programme einbetten und integrieren.
Die Java-Distribution liefert eine JavaScript-Engine aus, die sich allerdings von Java 6 auf Java 8 verändert hat.
· Java 6, Java 7: Rhino (https://developer.mozilla.org/en-US/docs/Rhino). Die JavaScript-Engine – in Java programmiert – kommt von Mozilla und basiert auf einer Implementierung von Netscape, die ihren Browser damals komplett in Java schreiben wollten. Die Browser-Implementierung „Javagator“ wurde zwar eingestellt, doch die JavaScript-Umgebung lebte weiter und Sun lizenzierte die Technologie und bettete sie (minimal verändert) in Java 6 und Java 7 ein.
· Ab Java 8: Nashorn (http://openjdk.java.net/projects/nashorn/, http://openjdk.java.net/jeps/174). Oracle entwickelte von Grund auf eine ganz neue JavaScript-Engine, die den Code ohne Interpretation direkt in Bytecode übersetzt und eine exzellente Performance und Kompatibilität mit ECMAScript-262 Edition 5.1 zeigt. Obwohl die JavaScript Edition 6 noch keine Rolle spielt, unterstützt Nashorn einige Spracherweiterungen, etwa Abkürzungen für Lambda-Ausdrücke. Da Nashorn nur JavaScript selbst unterstützt, Rhino aber noch einige Mozilla-Bibliotheken, kommt es zu Inkompatibilitäten, falls Nashorn unreines JavaScript ausführen soll.
[1] Bei anderen Java SE-Implementierungen muss das nicht zwingend gegeben sein.
NetBeans 7.3.1 auch mit Java EE 7 Unterstützung
Die Java 8 JVM wird keine Tail Call Recursion Optimierung bekommen
Endrekursion (engl. Tail Call Recursion) ist eine Besonderheit bei Methoden, dass sie mit einem rekursiven Aufruf enden. Zum Einstieg: Ist die bekannte rekursive Implementierung der Fakultät endrekursiv?
int factorial(int n) { if ( n == 0 ) return 1; return n * factorial( n – 1 ); }
Zwar sieht es optisch so aus, als ob die factorial(int) mit einem Methodenaufruf an factorial(…) endet, doch findet hier keine Endrekursion statt, da nach dem Methodenaufruf noch eine Multiplikation stattfindet – etwas umgeschrieben ist es besser zu erkennen:
int factorial(int n) { if ( n == 0 ) return 1; int fac = factorial( n – 1 ); return n * fac; }
Die Berechnung der Fakultät lässt sich umschreiben, so dass tatsächlich eine Endrekursion sattfindet, und zwar durch Einführung eines Containers für Zwischenergebnisse, genannt Akkumulator:
int factorial( int n )
{
return factorialTailrec( n, 1 );
}
private int factorialTailrec( int n, int accumulator )
{
if (n == 0) return accumulator;
return factorialTailrec( n – 1, n * accumulator );
}
Die umgeschriebene Version büßt gegenüber der ursprünglichen Version an Schönheit ein. Doch endrekursive Aufrufe sind attraktiv, da eine schlaue Übersetzungseinheit sie so optimieren kann, dass der rekursive Methodenaufruf durch einen Sprung ersetzt wird. In der Java Sprache haben wir keine direkten Sprünge, doch im Bytecode schon, sodass die Basis der Optimierung im Grunde so aussehen kann:
private int factorialTailrec( int n, int accumulator ) {
start:
if ( n == 0 ) return accumulator;
accumulator *= n;
n--;
goto start;
}
Die Rekursion ist durch eine ordinäre Schleife ersetzt, was Stack einspart und eine sehr gute Performance ergibt.
In funktionalen Programmen ergeben sich eher Situationen, in denen Endrekursion vorkommt, sodass es attraktiv ist, diese zu optimieren. Die Standard-JVM kann das bisher nicht, weil Java traditionell keine funktionale Programmiersprache ist, und Endrekursion eher selten vorkommt. Zwar wird die Optimierung von Endrekursion (engl. tail call optimization) immer wieder diskutiert und auch schon in
Prototypen ausprobiert, aber nie von der Oracle JVM implementiert.
Für Entwickler heißt dass, rekursive Aufrufe nicht umzuschreiben in endrekursive Varianten, da sie sowieso nicht optimiert werden und nur unleserlicher würden, und bei großen Datenvolumen, sprich Stack-Tiefe, auf die übliche nicht-rekursive iterative Version umzustellen. Im Fall von factorialTailrec(..) kann dies nämlich auch vom Entwickler gemacht werden und sieht so aus:
private int factorialTailrec( int n, int accumulator ) {
while (n != 0) {
accumulator *= n;
n–;
}
return accumulator;
}
Einmal Finalizer, vielleicht mehrmals die automatischen Speicherbereinigung
Objekte von Klassen, die eine finalize()-Methode besitzen, kann Oracles JVM nicht so schnell erzeugen und entfernen wie Klassen ohne finalize(). Das liegt auch daran, dass die automatische Speicherbereinigung vielleicht mehrmals laufen muss, um das Objekt zu löschen. Es gilt zwar, dass der Garbage-Collector aus dem Grund finalize() aufruft, weil das Objekt nicht mehr benötigt wird, es kann aber sein, dass die finalize()-Methode die this-Referenz nach außen gibt, sodass das Objekt wegen einer bestehenden Referenz nicht gelöscht werden kann und so zurück von den Toten geholt wird. Das Objekt wird zwar irgendwann entfernt, aber der Finalizer läuft nur einmal und nicht immer pro GC-Versuch. Einige Hintergründe erfährt der Leser unter http://www.iecc.com/gclist/GC-lang.html#Finalization.
Löst eine Anweisung in finalize() eine Ausnahme aus, so wird diese ignoriert. Das bedeutet aber, dass die Finalisierung des Objekts stehen bleibt. Die automatische Speicherbereinigung beeinflusst das in ihrer Arbeit aber nicht.
Reminder: Mein Java 8 Vortrag
Übermorgen Abend ist mein freier Vortrag über Java 8 bei der JUG in Braunschweig. Siehe auch http://www.tutego.de/blog/javainsel/2013/04/mein-abendvortrag-java-8-features-in-braunschweig-am-13-juni/.