Neues vom GC in .NET 4.0 und 4.5

Heute möchte ich etwas über Erneuerungen im .NET 4.0 / 4.5 sprechen. Das genannte bezieht sich auf den Workstation Garbage-Collector. Die Informationen für den Server Garbage-Collector entnehmen sie bitte den Links. Beginnen wir jedoch zunächst mit einer kurzen Auffrischung.

Wiederholung

Das .NET Framework unterteilt seinen Heap in verschiedene Generationen.

  • In der Gen0 werden fast alle Objekte erstellt. Die Anfangsgröße beträgt rund 256KB.
  • In der Gen1 werden Objekte gespeichert die eine Garbage-Collection überlebt haben. Die Anfangsgröße beträgt rund 2 MB.
  • In der Gen2 werden Objekte gespeichert die mehr als eine Garbage-Collection überlebt haben Die Anfangsgröße beträgt 10 MB.

Die soeben genannten Anfangsgrößen können zur Laufzeit variiert werden. Am stärksten wird sich i.A. die Größe der Gen2 verändern (wachsen), da die Gen2 als Endlager für alle länger benötigten Objekte dient.


GetHashCode dein Freund und Sorgenkind

Eine wichtige Methode beim Arbeiten im .NET Umfeld ist GetHashCode. Sie gibt einen 32 Bit Integer zurück der das Objekt identifizieren soll. Der Hash-Code beschreibt also die Identität des Objektes (im Gegensatz zur Speicherreferenz auf das Objekt).

Daraus leitet sich die Frage ab Wann zwei Objekte die selbe Identität besitzen? Im Falle einer Object-Relational-Mapper Klasse beispielsweise, wenn die Instanzen der O/R-Mapper Klasse auf ein und die selbe Zeile(n) der selben Tabelle(n) der selben Datenbank(en) verweisen. Klassischer weise durch eine Kette von Primary-Keys. Der Hash-Code ist auch ein Sorgenkind eines Entwicklers da schon hier die Probleme beginnen. Eine einfach Implementierungen könnte sein:


Muss es immer die 100% Lösung sein?

Ich behaupte einfach mal, dass man sich in der Softwareentwicklung schnell in zu aufwendigen Lösungen verliert. Zumindest mir geht es regelmäßig so, ich habe einiges an Software entwickelt und Artikel geschrieben die nie veröffentlicht wurden (obwohl sie dafür gedacht waren). Der Grund für die nicht Veröffentlichung war, dass sie meiner Meinung nach nicht komplett waren oder meinen eigenen Ansprüchen nicht genügten.

Das soll nicht bedeutet das die Artikel zu schreiben oder die Software zu entwickeln Zeitverschwendung war. Ganz im Gegenteil es ist immer beeindruckend wie viel man lernen kann, sobald man sich mit etwas anderen beschäftigt als den Arbeitsthemen. Die dabei gewonnenen Erkenntnisse sind, vielleicht auch für andere Interessant (ist schon ab und zu vorgekommen ;)). Daher resultiert für mich die Frage Muss es immer die 100% Lösung sein? wobei die simple Antwort Nein ist. Um Unklarheiten vorzubeugen damit ist nicht gemeint, dass man nur 80% der Anforderungen erfüllen soll. Vielmehr geht es um Erkenntnisaustausch/-gewinn.


Pipe aus eigenen Programmen nutzen

Mittels der von Unix Systemen bekannten Pipe (|) ist es auch unter Windows (via CMD-Line) möglich einzelne Kommandos zu verbinden. Die Pipe ermöglicht es die Ausgabe vom dem vorherigen Kommando direkt als Input des aktuellen Kommandos zu verwenden. Beispielsweise den Inhalt einer Datei einem Skript zu übergeben: type input.md | perl Markdown.pl > output.html

Logisch gesehen Ersetzt der Inhalt der Pipe ein einzelnes Konsolen-Argument. Um diese Funktionalität auch in den eigenen (Konsolen-) Programme verwenden zu können, sind im Allgemeinen nur zwei Erweiterungen notwendig.


Eindruck und Gedanken zu Mac OS X

Durch den Wunsch ein neues Notebook zu kaufen, stand ich vor der Wahl Linux, Windows oder Mac OS X. Da ich auf Arbeit Windows einsetze und früher in meiner Freizeit viel mit Linux (Ubuntu, Debian,  Linux Mint, Fedora) bzw. BSD (FreeBSD) gearbeitet habe ist die Wahl des Betriebssystems auf Mac OS X gefallen. Und die Wahl der Hardware auf ein Mac Book Pro 13,3" gefallen. Ich gebe zu das es mich immer interessiert hat zu Erfahren, warum Niemanden den ich kenne, sein Mac OS X Gerät missen möchte. In diesem Beitrag werde ich etwas über meinen Ersten Eindruck erzählen.


Immutable Objects am Beispiel von Passwort Hantierung in Java

In Java sind Strings „Immutable Objects“ (unveränderliche Objekte),
dass bedeutet sie werden zur Laufzeit nicht mehr geändert.  Immutables Objects haben viele Vorteile:

Sicherheit ist ein gutes Stichwort, denn Immutable Objects können auch Sicherheitsprobleme mit sich bringen. Schauen wir uns einmal Passwörter bei Java an. Diese sollten niemals in einem String gespeichert werden, da sie solange der String im Speicher existiert, im Klartext im Speicher stehen. Die allgemeine Empfehlung in verschiedenen Security Guides lautet daher Passwörter nur als Char-Array zu hantieren und sobald man das Passwort nicht mehr benötigt, den Inhalt dieses Array zu überschreiben. Überschreiben funktioniert mit Immutable Objects nicht, was ein Passwort in einem String zu einem Sicherheitsrisiko werden lässt.


Ermitteln des PID (Processidentifier) des Vaterprozesses

In manchen Fällen ist es notwendig heraus zu finden, welches der Vaterprozess eines Prozesses ist. Dafür gibt es im Allgemeinen drei verschiedene Lösungen im Windows .NET Umfeld.

Die häufigste Lösung ist die Verwendung von Performancecountern.

var process = FindProcess();  
using (var pC = new PerformanceCounter(
    "Process",  
    "Creating Process ID",  
    string.Format("{0}#{1}", process.ProcessName, 1),    
    process.MachineName))  
{  
    int pid = (int)pC.NextValue();  
    Console.WriteLine("parent pid = {0}", pid);  
}

Die Verwendung von Performancecountern im Allgemeinen kann zwei mögliche Nachteile haben:


DSLs, Extension Methods und Fluent Interfaces

In den letzten Jahren wurde in der Softwareentwicklung viel über Domänenspezifische Sprachen (domain specific language, kurz: DSLs) geschrieben. DSLs sollen von einem Domänenexperten gelesen werden können, auch ohne das die Domänenexperten über Programmierkenntnisse verfügen. DSLs können auch Entwicklern helfen die Quelltexte leserlicher zu machen, sowie Fehler zu vermeiden. Die Quelltextzeile:

if (!SessionEstablished)

Ist einfach verständlich (für diejenigen welche eine C ähnliche Syntax verstehen), als Alternative könnte folgende Quelltextzeile dienen:


Inversion Of Control(-Container), Service Locator und Dependency Injection

IOC-Container und DI sind zurzeit in vielen Fachzeitschriften diskutiert. Hier der Versuch einer kompakte Übersicht, die IOC, DI, SL und IOC-Container im Zusammenspiel erklärt.

Inversion Of Control

Beschreibt ein Paradigma zum Entwerfen von Frameworks. Ein Unterschied zwischen einem Framework und einer Bibliothek besteht darin, dass in einem Framework Methoden vom Verwender des Framework aufgerufen werden. Dies verändert den Kontrollfluss, bei einer klassischen Bibliothek, ruft der Verwender eine Methode auf, deren Funktionalität wird abgearbeitet und die Methode kehrt zum Aufrufer zurück. Die Steuerung des Kontrollflusses liegt also in der Hand des Verwenders der Bibliothek. Ein gutes Beispiel ist das .NET Framework, der Verwender kann Methoden über Events an Ereignisse binden, dass .NET Framework entscheidet, wann es die Funktionalität des Verwenders aufruft.


Vermeidung von switch-case zur Typen Bestimmung beim Aufruf von generischen Methoden

In der Entwicklung mit .NET hat man öfter folgendes Problem:

Methoden sind generisch implementiert und zu verwendende Objekte sind nur in Form von Referenzen auf Basistypen vorhanden (z.B. System.Array, System.Object). Diese Referenzen können nicht direkt an generische Methode übergeben werden (ergibt einen Compile Fehler).

Häufig liegen daher Typinformationen als String vor (über FullName-Property, aus Konfigurationsdatei, …). Diese Informationen werden anschließend verwendet, um den Typ der Referenz über switch-case aufzulösen.

Zum Beispiel: