Ein Decompiler ist ein Computerprogramm, das aus Objekt- oder Maschinencodes einen erkennbaren Text in einer Hochsprache hervorbringt. So ist dieser Quelltext für den Menschen lesbar. Andere Bezeichnungen für den Decompiler sind Dekompilierer, Reverse Compiler oder Reverse Engineering Compiler. Beim Dekompilieren versucht das Programm, den Vorgang des Kompilierens rückgängig zu machen. Oft kommt es zu Verwechslungen zwischen Decompiler und Disassembler. Die Assemblersprache ist jedoch nur ein anderes Darstellungsformat des Maschinencodes.

Wie funktioniert ein Decompiler?

Für die Kompilierung gibt es häufig keine Wandlungsfunktion. Die Dekompilierung macht das mit der Reverse-Engineering-Technik möglich. Diese Technik erzeugt nachträglich einen Quellcode, der die Basis eines ausführbaren Programmes ist. Der wiederhergestellte Code ist dem Quellcode der ursprünglichen Fassung sehr ähnlich, der zur Bildung des durchführbaren Programmes angewendet wurde. Sind in dem Programm auch noch Debug-Informationen hinterlegt, dann sind die angewandten Funktionsnamen, Module und Variablennamen des ursprünglichen Autors erzeugbar. In der Regel gehen Formatierungen des Ursprungs sowie Kommentare verloren, weil diese Infos üblicherweise nicht im Kompilat einbezogen sind.

Das Dekompilieren von Bytecodes (zum Beispiel .NET- und Java-Programme) ist im Allgemeinen einfacher als das Dekompilieren von Maschinencodes. Das liegt daran, weil die Systeme eine Menge Informationen des basierten Quellcodes in die Objektdatei aufnehmen. Zu vergleichen ist das mit der Debug-Version eines C++- oder C-Programmes. Die Namen der öffentlichen Bezeichner sowie die Typinformationen bleiben bestehen. Die vom Decompiler erzeugten Programmcodes sind allerdings nur funktional deckungsgleich mit der Quelldatei des Ursprungs.

Welche Einschränkungen bestehen beim Dekompilieren?

Der hergestellte Quellcode kann in einzelnen Fällen bis zur Unbenutzbarkeit verzerrt sein. Das ist der Fall, wenn keine Debug-Informationen enthalten sind und das Programm mit einer Optimierungsoption des Compilers übersetzt wurde. Wegen dieser Einschränkung ist das Dekompilieren dem Grunde nach ungeeignet, um verlorene Quelltexte wieder aufzuarbeiten. Die Quelltexte sollten deshalb in mehreren Sicherungen zur Verfügung stehen.

Im allgemeinen Gebrauch setzt ein Programmierer eher selten einen Decompiler ein. Hin und wieder kann es vorkommen, dass bei sehr alten Softwareversionen die ursprünglichen Quellen nicht mehr vorhanden oder auf Datenträgern gespeichert sind, für die kein geeignetes Lesegerät mehr vorhanden ist. Zu Beginn des elektronischen Datenverarbeitens war es zudem geläufig, kleinere Fehler durch Patchen der Objektdateien zu beseitigen. Diese Fälle sind neben der Rückentwicklung einer fremden Software die alleinigen Anwendungsgebiete, für die das Dekompilieren zur Anwendung kommt.

Welche rechtlichen Bestimmungen sind beim Anwenden der Decompiler zu beachten?

Softwareanbieter verweisen häufig in den Lizenzen darauf, dass die Dekompilierung der Produkte untersagt ist. Das Verbot soll auch für das Verändern der Software für den eigenen Gebrauch sowie für Studienzwecke gelten. Dem steht allerdings eine gesetzliche Regelung entgegen (§ 69e Urheberrechtsgesetz), die unter gewissen Voraussetzungen gestattet, ein Programm zu dekompilieren. Der Einsatz eines Decompilers ist nach dieser Regelung erlaubt, um die Kompatibilität mit einem unabhängig vom Ursprungsprogramm geschaffenen Computerprogramm zu erreichen. Die gesetzliche Bestimmung weicht somit die Lizenzvereinbarungen auf und macht diese ungültig.

Was ist ein Compiler?

Programmiersprachen wie JavaScript, Python oder Java sind so aufgebaut, dass diese vom Programmierer ohne Weiteres zu schreiben und zu lesen sind. Damit der Computer mit den jeweiligen Programmbefehlen etwas ausführen kann, muss der Code zuerst in eine begreifliche Sprache umgewandelt werden. Je nach Plattform und Programmiersprache erfolgt das Umwandeln von einem Interpreter oder Compiler. Ein Compiler ist das Gegenteil vom Decompiler, denn der Compiler ist eine Software, die Quellcodes in Maschinensprache umgestaltet. Beim Kompilieren übersetzt die Software das ganze Programm von einer Programmiersprache in eine Maschinensprache. Bevor das Computerprogramm ausgeführt werden kann, wird der Code in seiner Gesamtheit übersetzt.

Was ist ein Betriebssystem?

Das System stellt die Verbindung zwischen der Hardware und den Anwendungsprogrammen her. Ein Betriebssystem trägt auch die Bezeichnung OS (Operating System). Für die Vermittlung der Zugriffe auf die Hardware-Ressourcen ist das Betriebssystem zuständig. Das können Festplatten, Arbeitsspeicher, Drucker sowie USB-Ports sein. Auch Smartphones und Tablets benötigen ein Betriebssystem. Die gängigsten Systeme sind Linux, Android, Windows, Unix, iOS und Mac OS.

 

Die Verwaltung und Kontrolle der Hardware übernimmt das jeweilige Betriebssystem des Computers. Dazu zählen auch Geräte wie das DVD-Laufwerk, die Tastatur, der Drucker, die Maus und anderweitige Hardware-Schnittstellen, zum Beispiel USB-Ports. Eine Anwendungssoftware (beispielsweise MS Word) kann diese Tätigkeiten auch eigenständig durchführen. In diesem Fall müsste jedoch das Programm für die unterschiedlichen Hardwareausführungen eigene MS-Word-Versionen vorhalten. Ein Betriebssystem reduziert den Aufwand für die Programme und schafft zudem eine konforme Oberfläche, auf die eine Drittanbietersoftware ansetzen kann.

Was ist ein Server?

Ins Deutsche übersetzt steht das Wort Server für Diener. Der Begriff wird in der Informatik doppeldeutig gebraucht. Ein Server bezeichnet zum einen den Computer, der Ressourcen über ein Netzwerk bereitstellt. Zum anderen beschreibt ein Server das Programm, welches auf dem Computer läuft.

  1. Server (Hardware):

Ein Server, der hardwarebasiert agiert, ist eine in ein Computernetz eingefasste physische Maschine. Auf dieser laufen neben dem Betriebssystem ein oder auch mehrere softwarebasierte Server. Eine andere Bezeichnung für einen Server, der auf Hardware basiert, ist Host.

 

  1. Server (Software):

Ein softwarebasierter Webserver ist ein Computerprogramm, welches einen speziellen Dienst zur Verfügung stellt. Dieser Dienst kann von anderen Programmen (= Clients) lokal oder über ein Netzwerk genutzt werden. Es ist abhängig von der Art der Server-Software, welcher Dienst verfügbar ist. Beim Austausch der Daten setzen dienstspezifische Übertragungsprotokolle ein.

 

 

 

Bei einer Programmiersprache handelt es sich um eine formale Sprache, mit denen sich Algorithmen und Datenstrukturen für den Computer formulieren lassen. Diese sogenannten Rechenvorschriften werden dann von einem Computer interpretiert und ausgeführt. Sie bestehen normalerweise aus schrittweisen Anweisungen aus erlaubten textuellen Befehlen und Strukturen, die mit dem Begriff Syntax bezeichnet werden. Während die ersten Programmiersprachen noch direkt an die Eigenschaften des jeweiligen Computers ausgerichtet waren, kommen heute vorwiegend Programmiersprachen höherer Ebenen zum Einsatz.

Die Funktionsweise einer Programmiersprache

Die Gesamtheit aller Befehle und Anweisungen, aus denen sich ein bestimmtes Computerprogramm zusammensetzt, wird als Quellcode bezeichnet. Der Quellcode eines Programms lässt sich in einem einfachen Texteditor erstellen, wie beispielsweise Notepad oder Sublime Text. Bei größeren Software-Projekten kommen allerdings sogenannte integrierte Entwicklungsumgebungen (IDE) zum Einsatz. Moderne IDEs, wie zum Beispiel Visual Studio oder Intellij IDEA, unterstützen den Entwickler bei seiner Programmiertätigkeit und tragen wesentlich dazu bei, die Produktivität des Entwicklers zu optimieren. Damit ein Computer die im Quelltext enthaltenen Befehle und Anweisungen verarbeiten und ausführen kann, muss der Quellcode zunächst in die Maschinensprache des jeweiligen Computersystems übersetzt werden. Dieser Vorgang wird als Kompilierung bezeichnet.

Die Maschinensprache ist ein Binärcode, der für Menschen nur schwer verständlich ist und primär an die Anforderungen und Bedürfnisse von Computersystemen ausgerichtet ist. Der Quellcode kann zu verschiedenen Zeitpunkten in die Maschinensprache kompiliert werden. Falls der Quellcode zur Laufzeit des Programms kompiliert wird, kommt ein sogenannter „Just-in-Time-Compiler“ oder Interpreter zum Einsatz. Bei einigen höheren Programmiersprachen, wie beispielsweise Java, wird eine Kombination aus traditioneller und der JiT-Kompilierung eingesetzt. So wird beispielsweise noch vor der Programmausführung der Java-Code in einen Zwischencode, den sogenannte „Bytecode“ überführt. Dieser wird dann während der Ausführung des Programms in Maschinencode übersetzt.

Die einzelnen Bestandteile einer Programmiersprache

Eine jede formale Programmiersprache lässt sich anhand verschiedener Merkmale näher definieren. Zu diesen Merkmalen gehören neben der Syntax auch der Zeichensatz und das Vokabular.

 

Syntax: Bei der Syntax einer Programmiersprache handelt es sich um deren „Grammatik“. Die Syntax gibt die zulässigen Sprachelemente explizit an. Außerdem definiert sie auch, wie diese Elemente zu verwenden sind.

Vokabular: Das Vokabular bezieht sich auf reservierte Schlüsselwörter, die nicht als Namen für Variablen, Klassen, Funktionen und Methoden gewählt werden dürfen.

Zeichensatz: Der Zeichensatz einer Programmiersprache setzt sich prinzipiell aus alphanumerischen und numerischen Zeichen und einigen Sonderzeichen zusammen.

 

Die Leistungsfähigkeit und der Umfang einer Programmiersprache hängen in erster Linie von der Mächtigkeit des Befehlssatzes ab. Moderne Programmiersprachen besitzen mindestens die folgenden Befehle:

– Befehle zur Deklaration von Variablen und anderen Datentypen und Datenstrukturen, wie beispielsweise Arrays, Klassen, Hashmaps, die bei der Zwischenspeicherung von Daten genutzt werden

– Befehle, die bei der Ein- und Ausgabe von Daten zum Einsatz kommen

– Mathematische Funktionen, wie beispielsweise Addition, Division oder Multiplikation

– Funktionen zur Verarbeitung von Strings (Zeichenkette)

– Bedingte Anweisungen und Verzweigungen, die bei der Implementierung von Programmlogik zum Einsatz kommen.

– Steueranweisungen und Schleifen für die wiederholte Ausführung bestimmter Programmteile

Aus der Kombination dieser Grundfunktionalitäten lassen sich komplexere Strukturen und Funktionen erstellen. Viele Programmiersprachen bieten außerdem die Möglichkeit, gängige Befehle als Funktionen höherer Ordnung in sogenannte „Bibliotheken“ zu bündeln und somit programmübergreifend wiederverwendbar zu machen.

Gängige Programmierparadigmen im Überblick

Die erste höhere Programmiersprache wurde in den USA im Jahr 1954 entwickelt. Der US-amerikanische Informatiker John Warner Backus war für den Entwurf der Programmiersprache Fortran zuständig, die heutzutage als die älteste sich noch im Gebrauch befindliche Programmiersprache gilt. Einige Zeit später im Jahr 1959 machte der Logiker John McCarthy die Programmiersprache LISP der breiten Öffentlichkeit zugänglich. Noch im selben Jahr wurde mit COBOL die erste Programmiersprache für kommerzielle Anwendungsbereiche vorgestellt. Im Laufe der Jahre kamen noch zahlreiche Programmiersprachen hinzu. Alle formalen Sprachen lassen sich in Klassen einteilen, die als Programmierparadigmen bezeichnet werden. Zu den bedeutendsten Programmierparadigmen gehören die prozedurale, die funktionale und die objektorientierte Programmierung.

  1. Prozedurale Programmierung: Hierbei handelt es sich um das älteste Programmierparadigma. Bei der prozeduralen Programmierung setzt sich ein Computerprogramm aus einer Reihe von Anweisungen und Befehlen zusammen, die nacheinander ausgeführt werden. Der Programmablauf wird durch bestimmte Kontrollkonstrukte, wie Verzweigungen oder Schleifen, gesteuert. Zu den Programmiersprachen, die dieses Paradigma unterstützen, gehören Sprachen wie Fortran, Go oder C.
  2. Funktionale Programmierung: Bei dem funktionalen Programmierparadigma setzt sich ein Computerprogramm aus einzelnen Funktionen zusammen, die untereinander zu Funktionen höherer Ordnung verknüpft werden. Seinen Ursprung hat die funktionale Programmierung in der wissenschaftlichen Forschung rund um das sogenannte „Lambda-Kalkül“, das eine formale, mathematische Sprache zur Untersuchung von Funktionen darstellt. Zu den beliebtesten Sprachen, die das funktionale Programmierparadigma unterstützen, gehören Programmiersprachen wie Haskell, JavaScript und LISP.
  3. Objektorientierte Programmierung: Bei dem objektorientierten Programmierparadigma stehen Objekt im Mittelpunkt. Bei objektorientierten Sprachen, wie Python, C++ oder Java bestehen Computerprogramme aus kooperierenden Objekten. Ein Objekt zeichnet sich dadurch aus, dass es einer bestimmten Klasse angehört, dass es Eigenschaften (Attribute) besitzt und verschiedene Handlungen (Methoden) ausführen kann. Einzelne Objekte sind außerdem in der Lage, Nachrichten an andere Objekte zu senden und zu empfangen.

Ein Computer ist nicht selbständig in der Lage, die Anweisungen, die ein Entwickler in Form von Programmcode schreibt, zu verstehen. Die Codebefehle müssen entweder von einem sogenannten Compiler in Maschinensprache übersetze werden oder von einem sogenannten Interpreter zur Laufzeit interpretiert werden. Im folgenden Artikel gehen wir auf das Thema Compiler im Detail ein und schauen uns die Besonderheiten dieser Technologie im Kontext anderen Techniken an.

Was ist ein Compiler?

Moderne Programmiersprachen wie Java, Python oder JavaScript sind so konzipiert, dass sie von Programmierern ohne größere Probleme gelesen und geschrieben werden können. Damit ein Computer/PC mit den einzelnen Befehlen eines Programms etwas anfangen kann, muss der Quellcode erst in eine für den Computer verständliche Sprache übersetzt werden. Je nach Programmiersprache und Plattform wird das beispielsweise von einem Compiler oder Interpreter realisiert. Bei einem Compiler handelt es sich um eine Software, die Quellcode in Maschinensprache umwandelt. Konkret bedeutet das, dass ein Compiler das gesamte Computerprogramm von einer Programmiersprache in Maschinensprache übersetzt. Dabei wird der Programmcode in seiner Ganzheit übersetzt, bevor das Programm auf dem Computer ausgeführt wird.

In vielen Fällen wird noch ein Zwischenschritt eingeleitet, bevor das Programm in Maschinencode umgewandelt wird. In diesem Schritt wird der Quellcode des Programms zunächst in einen sogenannten „Zwischencode“ übersetzt, wie beispielsweise Objektcode oder Bytecode. Der Zwischencode bietet den entscheidenden Vorteil, dass er in den meisten Fällen auf unterschiedlichen Plattformen ausgeführt werden kann, ohne neu kompiliert werden zu müssen. Außerdem kann er auch von einem Interpreter verarbeitet werden, was beispielsweise bei der Programmiersprache Java der Fall ist. Aus diesem Zwischencode übersetzt der Interpreter dann Maschinencode, der von der jeweiligen Zielplattform verstanden wird. Per Linker wird dann eine ausführbare Datei (EXE-Datei) erstellt. Programmiersprachen höherer Ebenen, wie zum Beispiel Java oder C# arbeiten häufig mit Objekt- bzw. Bytecode, während Programmiersprachen, die nähere an der Hardwareebene sind, ausschließlich mit Maschinencode arbeiten.

Im Rahmen der Kompilierung leitet der Compiler mehrere Schritte ein, um den jeweiligen Quellcode in ein lauffähiges Computerprogramm umzuwandeln. Je umfangreicher und komplizierter der Quellcode ist, umso mehr Zeit und Ressourcen werden bei der Kompilierung benötigt. Sobald das Programm jedoch lauffähig ist, kann es viel schneller und effizienter ausgeführt werden als interpretierte Programme. Dies ist auf die Tatsache zurückzuführen, da alle Anweisungen und Systemaufrufe bereits vollständig in einer für den Computer verständlichen Maschinensprache vorliegen. Beispiele für reine Compiler-Sprachen sind Pascal, C und C++.

Was ist ein Interpreter?

Bei einem Interpreter, wie beispielswiese bei der BASIC-Programmiersprache, handelt es sich um ein Computerprogramm, das den Quellcode einer Anwendung zur Laufzeit verarbeitet. Der Interpreter geht dabei Zeile für Zeile vor: Ein Befehlt wird erfasst, analysiert und sofort ausgeführt. Danach geht es mit dem nächsten Befehl weiter, bis das Ende des Quellcodes erreicht ist oder alternativ ein Fehler den Vorgang zum Stillstand bringt. Sobald etwas nicht stimmt, unterbricht der Interpreter seine Arbeit. Dies liefert Entwicklern wichtige Informationen zur Fehlerbehebung. Man weiß als Entwickler sofort an welcher Stelle im Quellcode sich der Fehler befindet und man kann das Problem so schneller beseitigen.

Im Gegensatz zum Compiler erzeugt ein Interpreter keine ausführbare Datei, die man verteilen, kopieren oder mehrmals ausführen kann. Außerdem fertigt er auch keine Umwandlung des Quellcodes in Maschinensprache an, sondern er fungiert viel mehr als eine Zwischenschicht zwischen der Programmiersprache und dem Computer. Ein Interpreter wertet zur Laufzeit jeden einzelnen Befehl eines Computerprogramms aus und ruft die entsprechenden Funktionen und Systemaufrufe auf, welche die gewünschten Funktionen auf dem Zielsystem auslösen. Da ein Interpreter in Echtzeit arbeitet, wobei jeder einzelne Befehl bearbeitet werden muss, sind interpretierte Sprachen, wie beispielsweise Python oder JavaScript, langsamer und weniger effizienter als kompilierte Sprachen. So werden beispielsweise auch wiederkehrende Anweisungen immer wieder aufs Neue aufgerufen, was die Effizienz äußerst negativ beeinflusst.

Das Beste aus beiden Welten: der Just-in-time Compiler

Heutzutage gibt es moderne Ansätze, die Interpreter und Compiler vereinen und so die Nachteile der jeweiligen Systeme eliminieren. Der Just-in-time-Compiler übersetzt den Quellcode erst zur Laufzeit in Maschinensprache. Die Kompilierung wird also nicht bereits vorab realisiert. Nachdem der Quellcode erfolgreich kompiliert wurde, wird er vom Prozessor des Zielsystems verarbeitet. Gegenüber der traditionellen Kompilierung hat diese Vorgehensweise wesentliche Performance-Vorteile. Bei der Just-in-time-Kompilierung werden gesamte Codeblöcke reihenweise bearbeitet. Auch das bringt gegenüber der sonst üblichen zeilenweisen Bearbeitung des Quellcodes eine Leistungssteigerung mit sich.

Moderne JiT-Compiler sind in der Lage, einen für dynamische Sprachen optimierte Code zu generieren. Darüber hinaus bietet die Just-in-time-Kompilierung den entscheidenden Vorteil, dass vor dem Programmstart nur ein geringer Teil kompiliert wird, wodurch das Problem der Verzögerung des Programmstarts so gut wie eliminiert wird. Darüber hinaus wird äußerst effizient mit den System-Ressourcen umgegangen. Codefragmente, die überhaupt nicht durchlaufen werden, werden auch nicht kompiliert. Im Rahmen der JiT-Kompilierung werden einmal fertig kompilierte Codeblöcke in einem Zwischenspeicher aufbewahrt. Bei einer erneuten Kompilierung werden die benötigten Codeblöcke einfach aus dem Zwischenspeicher geladen und müssen nicht neu kompiliert werden.

Solaris ist ein Betriebssystem auf Basis von SunOS und einem Unix-Betriebssystem, das für Benutzerfreundlichkeit, Sicherheit und Kompatibilität steht. Das Unternehmen Oracle hat sich mehr als 20 Jahre mit dem Entwickeln der Geschäftsplattform beschäftigt und Funktionen integriert, die dem neuesten Stand der Marktentwicklung entsprechen. Die Abwärtskompatibilität ist dabei beibehalten worden. Frühere und aktuelle Anwendungen werden durch die binäre Anwendungssicherheit in einer fortschrittlichen Infrastruktur ausgeführt. Solaris gehört seit der Übernahme von Sun Microsystems im Jahr 2010 zu dem Unternehmen Oracle. Doch was ist eigentlich ein Betriebssystem und wie arbeitet ein Webserver?

Betriebssystem

Ein Betriebssystem trägt auch den Namen OS und das stammt aus der englischen Bezeichnung operating system. Das System sorgt für den Zugang auf die Hardware-Ressourcen des PC, wie beispielsweise auf Drucker, USB-Ports, Arbeitsspeicher und Festplatten. Neben dem Computer brauchen auch Smartphones, Tablets und andere PCs ein Betriebssystem. Die bekanntesten Betriebssysteme sind Android, Unix, Linux, Mac OS, Windows und iOS.

Das Betriebssystem kontrolliert und leitet die Hardware (=Komponenten des PCs). Dazu zählen auch folgende Geräte: DVD-Laufwerk, Drucker, Maus, Tastatur und anderweitige Schnittstellen, wie zum Beispiel USB-Ports. Dem Grunde nach wäre eine Anwendungssoftware, wie beispielsweise MS Word, in der Lage, diese Aufgaben eigenständig zu bewerkstelligen. In diesem Fall müsste jedoch das Programm spezielle MS-Word-Versionen für die unterschiedlichen Hardwareausstattungen des PCs bereithalten. Ein Betriebssystem reduziert den verwaltungsrelevanten Aufwand für die Anwendungsprogramme. Des Weiteren besteht eine einheitliche Oberfläche, die es ermöglicht, dass eine Software von anderen Anbietern ansetzen kann.

Was ist ein Webserver?

Ein Webserver ist eine Software oder auch eine Hardware. Die Hardware ist für das Ausführen der Software vorgesehen und kann Inhalte für das Internet bereitstellen. Der Webserver bearbeitet die eintreffende Netzwerkanforderung über HTTP sowie weitere verwandte Protokolle. Eine Interaktion mit dem Webserver erfolgt immer dann, wenn man das World Wide Web nutzt, um Mails einzusehen, um auf eine Website zu kommen sowie um eine Verbindung zu sozialen Netzwerken herzustellen. Der Server ist dafür zuständig, alle Anfragen an eine Internetadresse zu beantworten.

Die wichtigste Funktion des Webservers ist das Speichern sowie Verarbeiten der Internetseiten und das Liefern an Clients. Die Verständigung zwischen Server und Client läuft über das Hypertext Transfer Protocol (HTTP). Internetseiten sind in der Regel HTML-Dokumente, die aus Textinhalten, Stylesheets, Skripts und Bildern bestehen können. Wenn die Website stark genutzt wird, dann kommen häufig mehrere Webserver zum Einsatz.

Details zu Solaris

Die Kompatibilität zur System-V-Familie besteht seit 1990. Alle Versionen davor wurden unter der Bezeichnung Unix xx Sun Version yy bereitgestellt. Die Benennung SunOS fand Anfang 1986 mit der ersten öffentlichen SunOS-3.0 Beta eine erstmalige Verwendung. Diese Version wurde auf der Grundlage von BSD-Unix für die Anwendung auf Workstations und Servern von Sun hervorgebracht. Der Name Solaris entstand, als die Version 5.0 von SunOS auf dem Ursprung von UNIX System V entwickelt wurde.

Funktionen und Besonderheiten von Solaris

Seit der Ausführung von Solaris 7 besteht eine durchgängige 64-Bit-Unterstützung auf UltraSPARC-CPUs. 1991 erfolgte die Ankündigung der Solaris-Portierung für x86, welche im Jahr 1992 an den Start ging. Die x86er-Prozessor-Version ist seit 1992 nutzbar. Diese Version bootet seit 2004 auch auf AMD64. Das ermöglichte in der Version 10 eine 64-Bit-Unterstützung für Intel-64-CPUs oder AMD64-CPUs. Die Version von Solaris für PowerPC wurde nach der ersten Version (Solaris 2.5.1) wieder stillgelegt. Eine neue Übertragung begann nach Herausgabe von OpenSolaris unter der Bezeichnung Polaris.

Seit 2005 besteht das OpenSolaris-Projekt unter der Führung von Sun. Das Projekt stellt den Solaris-Quellcode unter der Distribution License und der Common Development der Allgemeinheit zur Verfügung. Im Juni 2005 fand die Freigabe des Open-Source-Betriebssystems statt. Das erfolgte unter dem Namen OpenSolaris und beinhaltete Quellen für Kernel, Bibliotheken und einzelne Module. Im Zuge dessen sollte auch ein Solaris-Release für PowerPC starten. Zu Beginn des Jahres 2006 wurde von den Systementwicklern eine Übernahme auf die Pegasos-basierte CHRP-Workstation ODW von IBM/Freescale/Genesi bekanntgegeben, aber es ist nie ein Release daraus hervorgegangen.

Solaris und die Software

Die Verwaltung der Solaris-Software basiert vordergründig auf eine Paketverwaltung mithilfe der pkg-Programme (=pkgchk, pkgadd, pkgrm etc.). Es ist möglich, zahlreiche Programme auf Solaris zu portieren, welche auf Unix- und verwandten Betriebssystemen laufen. Das macht es realisierbar, tausende zusätzliche Software-Pakete für Solaris bereitzustellen. Die Softwarepakete können beispielsweise durch das OpenCSW-Projekt mit dem Programm pkgutil eingespielt werden. Durch  Weiterentwicklung der Solaris Observability-Tools können Anwendungs- und Systemfehler in Echtzeit behoben werden. Das ermöglicht einen Verlaufs- und Echtzeiteinblick und Probleme sind einfach und zügig zu erkennen und zu lösen.

Schon seit Jahren gibt es Bestrebungen, diese Vielfalt konstruktiv zu vereinfachen und zu systematisieren. Write Once Run Anywhere bezeichnet einen Anspruch, der heute in ersten Fällen wirklich einlösbar geworden ist.

Virtualisierung als Grundlage von Write Once Run Anywhere

Hier betrachten wir hauptsächlich eine Virtualisierung eines Prozessors und eines Betriebssystems. Traditionell werden die in einer bestimmten höheren Programmiersprache geschriebenen Anweisungen interpretiert oder kompiliert in Befehle, die der Prozessor ausführen kann. Dasselbe gilt für das Betriebssystem, das System Calls bereitstellt, die von einem Anwenderprogramm aufgerufen werden können.

Virtualisierung bedeutet das Einziehen einer weiteren Schicht zwischen dem Anwenderprogramm und der Ausführung. Eine virtuelle Maschine bietet eine Menge von Befehlen und System Calls genau wie ein Prozessor mit einem Betriebssystem. Ein Anwenderprogramm wird in diesen Befehlssatz übersetzt und der virtuellen Maschine zur Ausführung übergeben. Jeder Befehl der virtuellen Maschine muss dann nochmals in Befehle des realen Prozessors übertragen werden.

Was bedeutet dann Write Once Run Anywhere hier? All dieser Aufwand muss schließlich einen Vorteil besitzen. Dieser liegt darin, dass nur die Übersetzung der Sprache der virtuellen Maschine in diejenige des Prozessors auf diesen Prozessor angepasst werden muss.

Die Virtualisierung der Programmiersprache Java

Hier ist es möglich, eine konkretere Antwort auf die Frage „Was bedeutet Write Once Run Anywhere?“ zu geben. Für Java wird auf den verschiedensten Plattformen eine JRE oder Java Laufzeitumgebung bereitgestellt. Diese entspricht einer virtuellen Maschine mit eigenen Funktionen, Befehlen und System Calls. Sie entspricht also in etwa einem eigenen Betriebssystem.

In Java entwickelte Software können Sie also auf allen diesen Plattformen laufen lassen, obwohl die Entwicklung nur einmal in der Sprache Java durchgeführt werden muss. Die technische Trennung bringt es auch mit sich, dass bei einem Absturz des Programms nur die JRE betroffen ist. Sie müssen also in einem solchen Fall nicht damit rechnen, dass der ganze Computer neu gestartet werden muss.

Probleme und Nachteile des „Write Once Run Anywhere“

– Die virtuelle Maschine nimmt eine bestimmte Rechenleistung in Anspruch. Diese steht dann für die Anwendungen nicht mehr zur Verfügung, was eine langsamere Ausführung zur Folge hat.

– Die Isolierung der realen Maschine durch die virtuelle ist aus den oben genannten Gründen gewollt, bringt aber auch nicht vermeidbare negative Konsequenzen mit sich. Die Speicherverwaltung ist nicht unter Ihrer direkten Kontrolle und das kann die Verarbeitungsgeschwindigkeit merklich beeinflussen. Deshalb wird die Verwendung von Java für Echtzeitsysteme mit zeitkritischen Anwendungen nicht empfohlen.

– Ihnen als Anwendungsentwickler stehen nur die von der JRE unterstützten Funktionen zur Verfügung. Der Prozessor Ihres Geräts mag noch weitere Befehle ausführen können, aber auf diese lässt sich durch die virtuelle Maschine nicht zugreifen. Das würde schließlich den Anspruch universeller Ausführbarkeit verletzen, da die entsprechenden Befehle eben nicht auf allen Prozessoren ausführbar sind.

Möglichkeiten der Umsetzung von Write Once Run Anywhere

Im Fall der JRE für Java wird der Anspruch der universellen Ausführbarkeit nur eingeschränkt erfüllt. Es können sich subtile Unterschiede zwischen der Ausführung eines für die JRE kompilierten Programms auf verschiedenen Plattformen ergeben. Auch die Gerätetreiber sind hinreichend unterschiedlich und auf die jeweiligen realen Geräte anzupassen, sodass die Ausführbarkeit nur eingeschränkt gegeben sein kann.

Schließlich sollten Sie auch bedenken, dass die Compiler und die Teile der JRE genauso wenig wie andere Software als fehlerfrei angesehen werden können. Durch verschiedene Fehler der JRE für unterschiedliche Plattformen ergibt sich ebenfalls unterschiedliches Laufzeitverhalten auf den entsprechenden Geräten.

Manche Programmierer haben deshalb die Erfahrung gemacht, dass die Antwort auf die Frage „Was bedeutet Write Once Run Anywhere?“ auch „Write once, debug everywhere“ lauten kann. Das Javaprogramm muss dann also auf den verschiedenen Plattformen zumindest getestet und gut möglicherweise auch korrigiert werden.

Es sollte auch bemerkt werden, dass dieselbe Software für verschiedene Plattformen auch einfach nicht wünschenswert sein kann, weil sie in einem solchen Fall keine Rücksicht auf unterschiedliche Erwartungen der Nutzer nehmen kann. So sind schon einfache Konventionen der grafischen Benutzeroberfläche verschieden wie etwa die Position der Buttons für das Speichern und Verwerfen von Änderungen an einer Datei. Wird ein solcher Unterschied nicht beachtet, kann das zu eingeschränkter Benutzerfreundlichkeit oder sogar zu Fehlern in der Benutzung führen.

Neue Antworten auf die Frage „Was bedeutet Write Once Run Anywhere?“

Ein neuer Zugang zu diesem Themenkreis ist der Dialekt Squeak der Programmiersprache Smalltalk. In diesem System wurde die universelle Ausführbarkeit im Wesentlichen komplett realisiert. Die strukturellen Einschränkungen dieses Zugangs kann aber auch Squeak logischerweise nicht vermeiden.

Softwareprodukte werden heutzutage in der Regel in Teams entwickelt, die ihre Arbeitsergebnisse in einer zentralen Build-Umgebung zu einer Einheit zusammenführen müssen. Der Continuous Integration-Ansatz (CI) sorgt dafür, dass neue Softwarekomponenten sofort flächendeckenden Tests unterzogen und danach zusammengeführt werden. Anstatt dies beispielsweise nur einmal täglich zu machen, werden im Rahmen des CI-Ansatzes neue Software-Builds erstellt, sobald eine Komponente für die Integration zugelassen wurde.

Softwareentwicklung und Kompilierung: ein Blick in die Vergangenheit

Eine Softwareanwendung setzt sich in der Regel aus einer Vielzahl einzelner Module zusammen. Dementsprechend ist die Vorgehensweise bei der Softwareentwicklung an diese speziellen Gegebenheiten angepasst, sodass das Gesamtprojekt häufig analog zu diesen Modulen von mehreren einzelnen Teams parallel entwickelt wird. Früher wurden Änderungen und Erweiterungen an dem Softwareprodukt in vielen Fällen in Form eines „Tagewerks“ realisiert. Konkret bedeutet das, dass die Zusammenführung der Änderungen, die von den isolierten Entwicklerteams innerhalb eines Arbeitstages erschaffen wurden, nur einmal täglich im Rahmen einer Kompilierung auf dem zentralen Build-Server konsolidiert wurden.

Erst danach wurden die neuen Funktionen und Features des Softwareprodukts im Kontext der erweiterten Codebasis getestet. Dieser traditionelle Ansatz der Softwareentwicklung birgt enorme Gefahren und Risiken. Falls ein neu geschaffener Code nicht kontinuierlich integriert und flächendeckenden Tests unterzogen wird, werden eventuelle Fehler im Code zu spät erkannt. Die Folgen sind zeitintensive und kostspielige Rückkopplungsprozesse. Vor der Einführung der Continuous Integration mussten einzelne Teams auf die Fertigstellung anderer benötigter Softwarekomponenten anderer Entwicklerteams warten, was sich auf die Effizienz des gesamten Projekts äußerst negativ auswirkt.

Continuous Integration im Überblick

Die Continuous Integration-Methoden, die in innovativen Unternehmen in Kombination mit DevOps zum Einsatz kommen, beziehen sich auf die kontinuierliche Integration einzelner Softwarekomponenten in die Gesamtcode-Basis (Codebase) des Softwareprojekts. Die wesentlichen Vorteile dieser Arbeitsweise spiegeln sich in den überschaubaren Schritten wider, die einen kontinuierlichen Arbeitsfluss fördern und die Möglichkeit bieten, Fehler in der Programmierung frühzeitig zu erkennen und zu beseitigen. Durch die gesteigerte Arbeitseffizienz ergibt sich eine höhere Softwarequalität. Die Arbeitsweise im Rahmen des Continuous Integration-Ansatzes unterscheiden sich stark, von der im obigen Absatz beschriebenen traditionellen Vorgehensweise. In Unternehmen, bei denen die kontinuierliche Integration zum Einsatz kommt, wird eine hohe Flexibilität gefordert.

Konkret bedeutet das, dass die in den kleineren Schritten vorgenommenen Änderungen oder Erweiterungen an dem Softwareprodukt in regelmäßigen Abständen zusammengeführt und getestet werden. Die Einspeisung wird über ein Versionsverwaltungssystem wie beispielsweise GitHub oder Bitbucket in einem unterteilten Code-Repository realisiert. Auf diesem Wege lassen sich Versionskontrollen durchführen, indem Build-Prozesse automatisiert werden, sodass stets die aktuelle Code-Version aus dem Repository übernommen wird.

Vor- und Nachteile von Continuous Integration

Obwohl der Continuous Integration-Ansatz zahlreiche Vorteile mit sich bringt, zeigt sich im Alltag auch, dass CI nicht nur Vorteile hat. Dass die langwierige Integrationsphase am Ende eines Softwareprojekts abgekürzt werden kann, lässt sich nicht beschreiten. Auftauchende Probleme können frühzeitig beseitigt werden. Für eingespielte Teams ist die Umstellung auf Continuous Integration jedoch oft mit Komplikationen verbunden. Anstatt dann effizienter zu arbeiten, kann das Verfahren sogar mehr Zeit in Anspruch nehmen.

Vorteile:

– kontinuierliches Feedback

– Fehler lassen sich frühzeitig identifizieren

– eine granulare Arbeitsweise wird gefördert

aktuelle und funktionsfähige Versionen sind stets verfügbar

– alle Änderungen werden im Detail protokolliert

Nachteile:

– es müssen flächendeckende Test-Abläufe entwickelt und implementiert werden

– Umstellung von einem gewohnten Arbeitsprozess

– es werden zusätzliche Server und Entwicklungsumgebungen benötigt

Welche Tools kommen bei Continuous Integration zum Einsatz?

Der Continuous Integration-Ansatz lässt sich grundsätzlich ohne spezielle Tools umsetzen. Das ist jedoch oft mit viel Aufwand verbunden und erfordert einiges an Disziplin. Aus diesem Grund ist es viel einfacher, sich die Arbeit mit den richtigen Tools zu erleichtern. Diese helfen meist bei der Versionskontrolle und beim Kompilieren und Erstellen von Builds. Die bekanntesten CI-Werkzeuge sind:

Jenkins: Hierbei handelt es sich um ein bekanntes Java-Programm, das im Rahmen moderner Continuous Integration und Continuous Delivery-Prozesse eingesetzt wird.

Travis CI: Dieses Tools ist insbesondere wegen seiner reibungslosen Integration mit GitHub beliebt. Für Open Source-Projekte ist es kostenlos, für kommerzielle Softwareprojekte muss eine offizielle Lizenz gekauft werden.

Bamboo: Auch hier handelt es sich um ein Tool, das in der Programmiersprache Java erstellt ist. Wie Travis CI ist es für kommerzielle Projekte normalerweise kostenpflichtig, während es für Open Source-Projekte kostenlos genutzt werden kann.

CodeShip: Dieses Tool basiert auf der Container-Technologie, die von IT-Größen wie Google, Microsoft und Red Hat aktiv weiterentwickelt wird und aus der modernen Softwareentwicklung nicht mehr wegzudenken ist.

Einsatzgebiete

Continuous Integration ist insbesondere im Umfeld agiler Softwareentwicklung in Kombination mit DevOps sehr beliebt. Dieser moderne Ansatz hat immer zum Ziel, in kleinen, übersichtlichen Schritten zu arbeiten. Heutzutage gibt es keine Rechtfertigung, ein Softwareprojekt ohne einen Continuous Integration-Ansatz zu betreiben. Dies liegt vor allem an dem Erfahrungsschatz sowie der großen Anzahl an verfügbaren Tools. CI kann sein volles Potenzial jedoch erst dann entfalten, wenn alle Team-Mitglieder optimal in alle Prozesse eingebunden werden und das System mittragen. Aus diesem Grund kommt einer reibungslosen Kommunikation eine sehr wichtige Rolle zu.