Isolationsprobleme in Java Transaktionen - Java Spektrum – • Robert Harbach, Wolfgang Rosenstiel, Wilhelm G. Spruth • Abstract Using Threads the Java Virtual Machine (JVM) is able to support several applications in parallel. Since, however, the JVM does not enable real application isolation, hosting several applications in one JVM can be critical if these applications represent transactions. Therefore, the common practice found in most Java application servers implies to run one JVM per application. Due to the fact, that this implies an overhead of computational resources, several, most often proprietary, solutions for application isolation in JVMs have been proposed in the past. This publication outlines isolation properties of a new JVM type, called a JVM Server that is integrated into the Customer Information Control System (CICS) [Ray11]. It implements the OSGi framework [OSG11b] and leads to major improvements in terms of application isolation. However, it is also shown that several known problems remain unsolved. Within this paper, solutions to these isolation exposures are proposed. Some of them are not based on the official Java release; others use existing CICS services for program control and are thus not applicable across the board. • Zusammenfassung Die Java Virtual Machine (JVM) ist in der Lage, mit Hilfe von Threads mehrere Anwendungsprogramme gleichzeitig zu betreuen. Dies kann kritisch sein, wenn es sich dabei um Transaktionen handelt, da die JVM keine echte Applikationsisolation ermöglicht. Das Hosting eines einzigen Anwendungsprogramms pro JVM ist deshalb eine übliche Vorgehensweise, was häufig einen ineffizienten Verbrauch von Rechenleistung zur Folge hat. Aus diesem Grund wurden bereits mehrere, meist proprietäre, Lösungen zur Applikationsisolation in JVMs vorgestellt. Diese Veröffentlichung beschreibt die Isolationseigenschaften eines neuen Typs der JVM, welche in das Customer Information Control System (CICS) [Ray11] integriert ist. Sie implementiert das OSGi Framework [OSG11b] und erreicht damit wichtige Verbesserungen. Es wird aber gezeigt, dass viele bekannte Isolationsprobleme weiterhin bestehen. Hierzu werden praktische Lösungsansätze als Abhilfe vorgeschlagen. Einige sind nicht Bestandteil des existierenden Java Standards. Andere nutzen bestehende CICS Services zur Kommunikation zwischen Programmen und sind somit nicht universell einsetzbar. Auf die Notwendigkeit einer langfristigen Lösung wird hingewiesen. 1. Einleitung Unternehmen und staatliche Organisationen verfügen heute über eine komplexe IT Infrastruktur. In großen Unternehmen besteht diese häufig aus Tausenden von Servern, zuständig für Aufgaben wie Sicherung des Netzwerks und der Applikationen, Routing und Switching, sowie das Hosting von (Web-)Applikationen. Dabei erfolgt die zentrale Datenhaltung auf einem oder mehreren Mainframe Servern (deutsche Bezeichnung Großrechner) mit dem z/OS Betriebssystem. Es besteht eine kritische Abhängigkeit der Unternehmen von ihren Datenbeständen. Deshalb haben Anwendungsprogramme, welche die Datenbestände einer Organisation abändern, meistens transaktionale Eigenschaften. Ein Anwendungsprogramm ist dann eine Transaktion, wenn es die ACID Eigenschaften (Atomicity, Consistency, Isolation, Durability) erfüllt [Gra93]. Transaktionen werden in den meisten Fällen mittels einer Middleware ausgeführt, die als Transaktionsmonitor oder Transaktions-Server bezeichnet wird. Diese stellt unter anderem mit Hilfe von Scheduling- und Synchronisationsmechanismen sicher, dass jede Transaktion strikt die ACID Eigenschaften implementiert. Zudem stellen die meisten Transaktionsmonitore bestimmte Services zur Kommunikation zwischen Anwendungen zur Verfügung. Darüber hinaus wird die Wiederherstellung des Datenbestands nach fehlerhaft ausgeführten Transaktionen ermöglicht (Stichwort Rollback). Verbreitete Transaktionsserver sind Tuxedo (BEA/Oracle), CICS (IBM), MTS (Microsoft) und SAP R/3. In den letzten 12 Jahren entstanden zusätzlich Web Application Server, welche für Transaktionen in der Programmiersprache Java entwickelt wurden. Beispiele sind Weblogic (BEA/Oracle), WebSphere (IBM) und NetWeaver (SAP) sowie Open Source Produkte wie Geronimo, Glassfish und JBoss. Transaktionen sind häufig „unternehmenskritische“ Anwendungen. Wir bezeichnen damit solche Anwendungen, deren fehlerhafte Ausführung zu nicht tolerierbaren Konsequenzen führt. Ein Beispiel ist ein Rundungsfehler in der letzten Dezimalstelle bei der Ausführung einer finanziellen Transaktion. Falls dieser Fehler auftritt, muss er, notfalls in tagelanger manueller Arbeit, identifiziert und rückgängig gemacht werden. 2. Problemdefinition Ein transaktionales Anwendungsprogramm besteht häufig aus den zwei Komponenten: Präsentationslogik und Geschäftslogik (Business Logic). Während die Geschäftslogik die eigentliche Arbeit verrichtet, dient die Präsentationslogik dazu, die Ergebnisse der Geschäftslogik auf eine attraktive Art auf dem Bildschirm darzustellen. In der populären Model View Controller Triade entspricht das Modell der Geschäftslogik und der View der Präsentationslogik [Moe93]. Seit der Einführung von Java im Jahr 1995 existiert ein Interesse, die Sprache auch für transaktionale Anwendungen einzusetzen. Hierzu erschien 1999 die als Java Enterprise Edition (JEE) bezeichnete Erweiterung. Während Java für die Implementierung der Präsentationslogik seitdem einen Siegeszug angetreten hat, erfolgte der Einsatz für die Geschäftslogik unternehmenskritischer Anwendungen bisher nur sehr zögerlich. Hierfür existieren mehrere Gründe. Ein wichtiger Grund sind unzureichende Eigenschaften, welche die Isolation (I in ACID) der Transaktionen sicherstellen. Isolationsprobleme der JVM sind seit Einführung des JEE-Standards bekannt, siehe z. B.: „The existing application isolation mechanisms, such as class loaders, do not guarantee that two arbitrary applications executing in the same instance of the JVM will not interfere with one another. Such interference can occur in many places. For instance, mutable parts of classes can leak object references and can allow one application to prevent the others from invoking certain methods. The internalized strings introduce shared, easy to capture monitors. Sharing event and finalization queues and their associated handling threads can block or hinder the execution of some application. Monopolizing of computational resources, such as heap memory, by one application can starve the others [Cza00]“. Oder: „Java gives the virtuoso thread programmer considerable freedom, but it also presents many pitfalls for less experienced programmers, who can create complex programs that fail in baffling ways [San04]“. 3. Bisherige Lösungsansätze In der Vergangenheit sind eine Reihe von Lösungsvorschlägen entwickelt worden. Diese wurden jedoch häufig wieder verworfen. Die meisten Isolationsprobleme einer JVM basieren auf der Tatsache, dass die JVM über keine Ressourcen-Management Funktionen verfügt. Spezifisch wurde die JVM nicht für den Betrieb mehrerer Applikationen entworfen. Aus diesem Grund läuft in vielen Applikationsservern pro Anwendung eine virtuelle Maschine. Dadurch wird sichergestellt, dass Anwendungen sich gegenseitig nicht beeinflussen. Dieses Vorgehen führt jedoch zu einer ineffizienten Nutzung der Ressourcen, insbesondere im Zusammenhang mit der Erstellung und dem Abbau der einzelnen JVMs. Ein vielversprechender Ansatz zur Lösung der Isolationsprobleme war die Application Isolation API [Jav06]. Obwohl dieser Ansatz die meisten Isolationsprobleme beseitigte, wurde die Application Isolation API bisher in keinem offiziellen Java Release veröffentlicht. Ein weiterer interessanter Ansatz zur Lösung bestehender Isolationsprobleme in JVMs war die Persistent Reusable Java Virtual Machine (PRJVM) [IBM01], die speziell für den CICS Transaktions-Server entwickelt wurde. Die PRJVM implementierte einen Mechanismus für die Wiederherstellung des Status der VM vor etwaigen Programmausführungen. Obwohl dieser Ansatz einen Ausgleich zwischen effizientem Ressourcenverbrauch und Applikationsisolation darstellte, wurde die PRJVM von einer neuen JVM-Implementierung, dem „JVM Server“, ersetzt. Ein JVM Server ist eine Laufzeitumgebung der JVM innerhalb von CICS, die eine Standard JVM mit einem OSGi Framework enthält. Anwendungen laufen innerhalb dieses Frameworks als so genannte Bundles. Ein Bundle besteht aus einem Java Archive (jar) und einer Inhaltsbeschreibung (MANIFEST.MF). Die vorliegende Veröffentlichung beschreibt im folgenden einige der heute existierenden Isolationsprobleme und diskutiert Lösungsmöglichkeiten. Manche Lösungsansätze benötigen hierzu Funktionen der Middleware, in der die JVM eingesetzt wird, und sind deshalb nicht portierbar. Unsere Untersuchungen basieren auf die Version der JVM, welche in dem „JVM Server“ des CICS Transaction Servers Version 4.2 seit 2011 verfügbar ist. CICS (Customer Information Control System) ist ein Transaktionsmonitor der Firma IBM mit Applikationsserver Funktionalität. Die wichtigsten Gründe für den Einsatz von CICS als Applikationsserver sind, neben seiner weiten Verbreitung in Enterprise Systemen, die zahlreichen verfügbaren Services, die unter anderem Transaktionssicherheit ermöglichen. Darüber hinaus agiert CICS als Middleware und ermöglicht dadurch den Betrieb unterschiedlicher Anwendungen ungeachtet der verwendeten Programmiersprache. Damit ist eine einheitliche Kommunikation zwischen Anwendungen möglich. 4. Java Integration in CICS CICS unterstützt seit 1998 das Hosting von Java Applikationen [IBM11-c]. Typisch basiert die Java Unterstützung auf einem Pool von JVMs. Diese Lösung wird in Zukunft durch den JVM Server ersetzt. Im Folgenden werden die zwei verschiedenen Modelle der Java Unterstützung beschrieben. 4.1 Pooled JVMs Ein Pool von JVMs ist eine Laufzeitumgebung für eine vordefinierte Anzahl an JVMs innerhalb vom CICS. Diese Laufzeitumgebung stellt sicher, dass in jeder JVM nur eine Anwendung, bzw. Transaktion, gleichzeitig aktiv ist. Die JVMs werden von den einzelnen Transaktionen seriell verwendet (siehe Abbildung 1). Abbildung 1: Grafische Darstellung der seriellen Verwendung von Pooled JVMs durch mehrere Transaktionen. Nach [IBM11-b]. Wie in [IBM11-b] beschrieben haben die JVMs innerhalb des Pools drei verschiedene Betriebsmodi: • Single Use ◦ Neuerstellung der JVM nach erfolgter Transaktion • Reusable ◦ Wiederverwendung der JVM für mehrere aufeinanderfolgende Transaktionen • Resettable (auch Persistent Reusable Virtual Machine genannt, siehe [IBM01]) ◦ Wiederherstellung des Zustandes der JVM nach erfolgter Transaktion Auf einem Hochleistungsserver werden mehrere hundert oder tausend Transaktionen pro Sekunde verarbeitet. Trotz der Isolationsvorteile des „Single Use“ Modus, ist dieser für viele Anwendungen nicht geeignet, da die Dauer der Erstellung einer neuen JVMs im hohen Millisekundenbereich angesiedelt ist. Auch der Reusable Modus birgt Nachteile. Beispielsweise kann eine Anwendung durch die Modifikation einer statischen Systemvariable einen direkten Einfluss auf nachfolgende Anwendungen haben, falls diese nicht wieder zurückgesetzt wird. Unter Berücksichtigung der Eigenschaft, dass der Resettable Mechanismus ebenfalls Zeit in Anspruch nimmt, kann auch der Resettable Modus nur bedingt als geeigneter Lösungsansatz der Isolationsprobleme betrachtet werden. Die Ressourcenprobleme in Pooled JVMs werden durch den neuen CICS JVM Server verbessert. 4.2 JVM Server Ein JVM Server ist eine Laufzeitumgebung für die Ausführung von CICS Java Applikationen. Diese beinhaltet nur eine JVM und wird von mehreren Anwendungen parallel verwendet. Zudem enthält der JVM Server ein OSGi Framework (siehe Abbildung 2), welches die Isolation und die Modularität von Anwendungen ermöglicht. Dabei wird die Isolation mit Hilfe von Class Loadern bewerkstelligt, eine Methode, die bereits 1997 von Balfanz und Gong [Bal97] beschrieben wurde und auch in JEE verwendet wird [Chi09]. Dieser Ansatz basiert auf der Eigenschaft, dass Objekte, die von unterschiedlichen Class Loadern erstellt wurden, sich in unterschiedlichen Namensräumen befinden und somit keinerlei Kenntnis voneinander besitzen. Wie jedoch in [Mcg99] beschrieben, besteht kein Schutz gegen eine Überschneidung der Namensräume (siehe Kapitel 5). Abbildung 2: Grafische Darstellung der JVM Server Laufzeitumgebung in CICS Das OSGi Framework kapselt Anwendungen bzw. Funktionen (je nach gewünschter Granularität) in sogenannte Bundles, die laut [IBM11-b] auch als Plain Old Java Objects (POJOs) [Fow00] betrachtet werden können. Ein Bundle hat mehrere Zustände, darunter Uninstalled, Installed, Resolved und Active [OSG11b]. Die Administration der Zustände der Bundles innerhalb einer aktiven JVM erfolgt mit Hilfe des OSGi Frameworks. Dies ermöglicht die Installation einer neuen Anwendung in den JVM Server ohne Neustart der JVM. Im Gegensatz dazu ist bei den meisten Java Applikationsservern ein Neustart für ein erfolgreiches Deployment einer neuen Anwendung notwendig. Die Zustände der Bundles werden in der Regel über ein Interface gesteuert – die OSGi Konsole. Im Falle des JVM Servers wird dieses Interface durch den CICS Explorer, eine auf Eclipse basierende Anwendung, repräsentiert. Da jedes Bundle einen eigenen Class Loader besitzt, sind Objekte standardmäßig voneinander isoliert. Diese Art der Isolation ist jedoch unvollständig [Mue05]. Im folgenden Abschnitt wird dies näher erläutert. 5. Offene Isolationsprobleme in JVMs Im Rahmen unserer Untersuchung wurden die Erkenntnisse von Müller [Mue05], sowie Erkenntnisse von Parrend und Frenot [Par09], berücksichtig. [Mue05] zeigte bereits 2005 eine größere Anzahl von JEE Isolationsproblemen auf. [Par09] beschreibt Isolationsprobleme des OSGi Frameworks. Basierend auf den Erkenntnissen von [Mue05] und [Par09] wurde in praktischen Versuchen überprüft, welche bekannten Probleme der JVM und dem OSGi Framework in einen transaktionalen System basierend auf CICS anwendbar sind. Hierfür wurde, wie oben beschrieben, die JVM Server Laufzeitumgebung in CICS verwendet. Im Detail wurden die folgenden Probleme praktisch nachgebildet. Die einzelnen Versuche und Ergebnisse inklusive verwendetem Quellcode sind in [Har12-a] beschrieben. Aus Gründen der Vereinfachung werden im folgenden OSGi Bundles als Anwendungen bzw. als Transaktionen interpretiert. 5.1: Probleme mit Systemklassen Da, wie in [Cza00] beschrieben, Systemklassen nicht repliziert werden und die Class Loader Isolation somit keinen Einfluss auf die Systemklassen hat, sind die bekannten Probleme, die auch Müller in [Mue05] beschrieben hat, wie die Manipulation von statischen Feldern oder der Zugriff auf potentiell gefährliche Methoden von Systemklassen auch im JVM Server nicht behoben. Ändert beispielsweise Klasse A aus Bundle X die Dateitrenner (file separator) Systemeigenschaft mit Hilfe der setProperty Methode der Systemkasse System, so ist diese Änderung global und somit für Klasse B aus Bundle Y sichtbar. Des Weiteren ist es nach wie vor möglich, die gesamte JVM mit Hilfe der Methode exit der Systemklasse System (oder der Methode halt der Systemklasse Runtime) zu beenden. Da jede Anwendung in einer JVM einen Thread repräsentiert (siehe [Lin99]), kann zudem die auch Verwendung einiger Methoden der Systemklasse Thread zu großen Problemen führen. Beispielsweise ist es mit Hilfe der Methode getAllStackTraces möglich auf einzelne Threads zuzugreifen und diese mit Hilfe der deprecated Methode suspend zu beenden. Der Zugriff auf Systemklassen und deren Methoden kann aus jeder Klasse (und jedem Bundle) stattfinden; somit repräsentiert jeder einzelne genannte Fall ein Isolationsdefizit. 5.2: Überschneidende Namensräume Aufgrund der Benutzung verschiedener Class Loader und der daraus resultierenden Namensräume, sind einzelne Bundles standardmäßig voneinander isoliert. Bei Verwendung eines Features des OSGi Frameworks, dem so genannten „wiring“ (siehe [OSG11b]), kann Isolationseffekt der Class Loader umgangen werden. Wiring ermöglicht generell die Kommunikation zwischen Bundles. Hierfür kann ein Bundle bestimmte Klassen exportieren und diese dadurch für andere Bundles zur Verfügung stellen. In einigen Fällen führt diese Überschneidung der Namensräume jedoch zu Problemen. Exportiert beispielsweise Bundle A die Klasse A, die von verschiedenen Bundles importiert wird, so wird wie in [Lip08] beschrieben basierend auf dem Delegationsmechanismus (siehe [OSG11b]), der gleiche Class Loader für die Erstellung aller Instanzen (aus allen Bundles) der Klasse A verwendet. Statische Variablen aus Klasse A sind somit für alle Instanzen aus allen Bundles global. Noch gravierender ist der konkurrierende Zugriff zwischen Bundles mit Hilfe von Threads. In diesem Fall werden Synchronisationsprobleme zu Isolationsproblemen, da durch Rata Races Bundles einen undefinierten Einfluss aufeinander haben können und somit gegen die Isolationseigenschaft von Transaktionen verstossen. Der Einsatz von Synchronisationsmechanismen kann in diesem Fall nur bedingt als Lösung angesehen werden, da hängende Threads in synchronisierten Methoden zu mehreren hängenden Bundles und somit zu Anwendungsübergreifenden Deadlocks führen können. Dies repräsentiert erneut ein Isolationsdefizit. 5.3: Das Java Native Interface Wie in [She99] beschrieben, ermöglicht Java die Ausführung von platformabhängigem C/C++ Code. Hierfür stellt die JRE eine Schnittstelle namens Java Native Interface (JNI) zur Verfügung. Mit dessen Hilfe können C/C++ Anwendungen aus eine Java Klassen heraus gestartet werden. Wichtig zu erwähnen ist, dass die gestarteten C Anwendungen Zugriff auf den Stack und den Heap der JVM haben. In diesem Zusammenhang hatte Müller [Mue05] gezeigt, dass Probleme wie Segmentation Faults im platformanhängigen Code durch den Absturz der JVM alle aktiven Anwendungen beeinträchtigen. Der gleiche Effekt trat auch in unserer Testumgebung auf. Darüber hinaus wurde auch gezeigt, dass das JNI die unrechtmäßige Manipulation von privaten Variablen auch im CICS Umfeld ermöglicht. Grund hierfür ist die Eigenschaft der Programmiersprache C, die keine Zugriffsklassen (access modifier) für Variablen vorsieht. Folglich ist die Manipulation einer privaten Variable, abgelegt im Stack, möglich. 5.4: Übermäßiger Ressourcenverbrauch Wie bekannt, besitzt Java keinerlei Funktionen zur Verwaltung der Ressourcen. Aus diesem Grund darf jede Applikation innerhalb einer JVM so viele Ressourcen verbrauchen wie nötig. Ein übermäßiger Ressourcenverbrauch hat jedoch enorme Auswirkungen auf andere Applikationen, die in der gleichen JVM aktiv sind. In diesem Zusammenhang wurden übliche Probleme, unter anderem beschrieben in [Par09], wie Endlosschleifen, rekursive Erstellung von Threads und Memory Leaks im CICS Umfeld untersucht. Darüber hinaus wurde ein OSGi spezifisches Problem nach [Par09], die endlose Registrierung von Services, umgesetzt. Recht trivial aber dennoch gravierend sind Endlosschleifen. Diese konsumieren laut [Par09] viel Rechenleistung und können somit zu einer Verlangsamung anderer Applikationen führen. In unserem Versuchsaufbau führten Endlosschleifen sogar zu einem Neustart der JVM und somit zu einem Abbruch aller aktiven Applikationen. Der Grund hierfür ist eine Vorsichtsmaßnahme des Transaktionsmanagers CICS, welches die Endlosschleife erkennt und dadurch einen kontrollierten Neustart der Applikationen hervorruft. Da die JVM jedoch mehrere Applikationen betreut, führt ein Neustart der JVM zu einem Abbruch aller Java Anwendungen. Ein weiteres Beispiel entnommen aus [Par09] für übermäßigen Ressourcenverbrauch ist die rekursive Erstellung von Threads. Diese führen schnell zu JVM Neustarts. Etwas komplexer aber dennoch problematisch sind so genannte Memory Leaks. Ein Memory Leak ist in der Regel ein Fehler im Programmcode, welcher die automatische Speicherbereinigung, die so genannte garbage collgection, für bestimmte Objekte außer Kraft setzt. Wie in [Nyl99] beschrieben, gehen viele Entwickler aufgrund der garbage collection in JVMs davon aus, dass Java frei von Memory Leaks ist. [Din04] beschreibt jedoch, dass Java Objekte nur gelöscht falls auf diese nicht referenziert wird. In einigen Fällen ist dieses Vorgehen nicht effektiv, da nicht referenzierte Objekte sich dennoch im Heap befinden können. In praktischen Versuchen, dokumentiert in [Har12], wurden Memory Leaks im JVM Server umgesetzt. Die Ergebnisse zeigen, dass auch unter der Kontrolle von CICS, Java Memory Leaks zu Isolationsproblemen führen, da entweder der Speicherbereich verkleinert wird oder, falls die maximale Heap Größe überschritten wird, CICS einen JVM Neustart durchführt. Ein ähnliches Verhalten zeigt der JVM Server auch bei unendlichen Service Registrierungen. Wie in [Par09] beschrieben, kann eine Anwendung eine unendliche Menge an OSGi spezifischen Services registrieren. Dies führt ebenfalls zur Überschreitung des maximalen Speichers und somit zu einem Neustart der JVM. Die Ergebnisse zeigen, dass alle untersuchten Probleme zu Denial of Service führten und somit in JVM Servern gültig sind. 5.5: Probleme mit Activator Klassen Das OSGi Framework beinhaltet sogenannte Activator Klassen (siehe [OSG11b]). Diese werden beim Start und beim Beenden der Bundles aufgerufen und dienen dem Entwickler zur Erstellung von Objekten und deren Bereinigung beim Start bzw. beim Beenden des Bundles. Parrend und Frenot haben in [Par09] mit Hilfe dieser Klassen bei Implementierung einer Endlosschleife und eines hängenden Threads ein Denial of Service Problem hervorgerufen. Dies führte zu einer aufgehängte Administrationsoberfläche. Obwohl diese Klassen in JVM Servern nicht benötigt werden (siehe [IBM11-b]), ist deren Verwendung nicht untersagt. In einem praktischen Beispiel wurde das Problem nach [Par09] reproduziert. Trotz der Tatsache, dass der JVM Server explizit nur über das CICS Explorer Interface administriert wird, erhielten wir ähnliche Resultate wie in [Par09]; sprich eine Aufhängung des CICS Explorers. Somit gelten die Probleme aus [Par09] im Bezug auf Activator Klassen uneingeschränkt auf den JVM Server. 5.6: Unrechtmäßige Kontrolle Wie in [OSG11b] beschrieben stellt das OSGi Framework bestimmte Services für die Verwaltung der Zustände von Bundles zur Verfügung. Mit Hilfe dieser kann ein Bundle andere Bundles steuern und gegebenenfalls deinstallieren. Obwohl diese Funktionalität in vielen Fällen sinnvoll scheint, stellt sie aus Sicht der Anwendungsisolation ein Problem dar. Hinzu kommt das in [Par09] beschriebene Problem bezüglich der Fragment Bundles. Ein Fragment stellt eine nachträgliche Erweiterung eines Bundles nach dessen Deployment dar. Dadurch werden Modifikationen am Bundle ohne größere Probleme bewerkstelligt. Laut [OSG11b] sind Übersetzungsdateien für Applikation einer der hauptsächlichen Anwendungsfälle. Nun kann ein Fragment die Sichtbarkeit von Klassen mit Hilfe der wiring Funktionalität (sprich export einer Klasse) eines Bundles verändern ohne dass dieses davon Kenntnis bekommt. Dies kann zu unerlaubten Überschneidungen der Namensräume führen und stellt somit ebenfalls ein Problem im Bezug auf Applikationsisolation dar. 6. Praktische Lösungsansätze Um Abhilfe unter Einbindung bestehender, real existierender, Möglichkeiten im Bezug auf die offenen Isolationsprobleme zu schaffen, wurden praktische Lösungsansätze untersucht. Diese werden im Folgenden aufgelistet (Details in [Har12-a]). 6.1 Statische Programmanalyse Wie in [Rep04] beschrieben, dient statische Programmanalyse dazu alle möglichen Status eine Applikation ohne spezifische Eingabedaten zu überprüfen. In der Regel werden diese Analysen automatisch mit Hilfe von Tools bewerkstelligt. Im Bezug auf Systemklassen stellt die Application Isolation Utility, beschrieben in [IBM11-a], eine passende Lösung dar. Das Tool untersucht den Programmcode einer Java Anwendung und identifiziert Zugriffe auf Methoden der Systemklassen und statische Variable sowie deren Manipulation. Weitere Tools wie FindBugs (siehe [Aye07]) können zur Identifikation von Endlosschleifen verwendet werden und minimieren das Risiko eines Denial of Service (siehe 5.4). 6.2 Java und OSGi Security Java beinhaltet standardmäßig die Möglichkeit zur Programmkontrolle mit Hilfe des Java Security Managers. Nach Aktivierung laufen alle kritischen Operationen, wie Zugriffe auf Systemklassen, lokale Ressourcen oder Threads unter der Kontrolle des Security Managers. Berechtigungen werden als „white list“ in einer policy file vergeben. Darüber hinaus kann der Security Manager nach Belieben erweitert werden. Dadurch kann der Zugriff auf potentiell schädliche Methoden von Systemklassen wie exit unterbunden werden. Neben dem Standard Java Security Manager enthält der JVM Server aufgrund des OSGi Frameworks einen weiteren Security Layer. Dieser ist im Grunde genommen ein modifizierter Security Manager, der OGSi spezifische Berechtigungen, beispielsweise zur gegenseitigen Kontrolle der Bundles, beinhaltet. Damit können alle Probleme im Bezug auf Systemklassen (siehe 5.1) sowie alle Probleme im Bezug auf unrechtmäßige Kontrolle (siehe 5.6), gelöst werden. 6.3. Monitoring Obwohl die meisten statischen Programmanalyse-Tools offensichtliche Probleme wie Endlosschleifen erkennen, ist das Problem des übermäßigen Ressourcenverbrauchs bei deren Einsatz nicht vollständig gelöst. Probleme wie hängende Threads, Memory Leaks oder simple übermäßige Nutzung des Speichers bleiben offen. Um diesbezüglich dennoch Abhilfe zu schaffen, eigen sich Monitoring Tools, die den Zustand der JVM in Echtzeit überwachen. In unserer Testumgebung auf CICS bewährten sich der JVM Server spezifische Monitor namens Java Health Center (siehe [IBM]). Diese erkannten Memory Leaks und größeren Speicherverbrauch in Echtzeit. Trotz der Tatsache, dass Monitoring manuelle Interaktion voraussetzt, ist diese Lösung als praktischer Lösungsansatz die einzige derzeitige Möglichkeit um Denial of Service spezifische Isolationsdefizite zu beheben. 6.4 CICS Services In einigen Fällen ist es unabdingbar platformabhängigen Code zu verwenden. Da CICS als Middleware zwischen Anwendungen agiert und somit spezifische Services zur Kommunikation zwischen Applikationen ermöglicht, ist die Lösung aller Probleme im Bezug auf das Java Native Interface (siehe 5.3), die Verwendung von CICS Services zur Kommunikation anstatt des JNI. Mit Hilfe dieser Services ist selbst die Kommunikation transaktional und bringt somit einige Vorteile mit sich. 7. Schlussfolgerung und Ausblick Es wurde gezeigt, dass die meisten bekannten Isolationsprobleme auch innerhalb eines transkationsbasierten Enterprise Umfelds gültig sind. Die meisten untersuchten Probleme können jedoch mit Java oder Framework spezifischen Bordmitteln gelöst werden. Ungelöste Probleme wie Endlosschleifen oder hängende Threads können zumindest mit bestimmten Tools identifiziert werden. Allein hängende Threads in Activator Klassen konnten weder behoben noch zur Laufzeit identifiziert werden, da ein hängendes Management Interface, in unserer Testumgebung der CICS Explorer auch das live Monitoring, in unserem Fall das Java Health Center, beeinflusst. Trotz all der Vorteile bringen die Lösungsansätze auch einige Nachteile mit sich. Statische Programmanalyse beispielsweise garantiert nicht die Erkennung potentieller Probleme und kann somit nicht als verlässliche Lösung angesehen werden. Wie in [Her05] gezeigt, kann der Java Security Manager eine Applikation stark verlangsamen; und obwohl keine vergleichbaren Publikationen zum OSGi Security Layer verfügbar sind, kann davon ausgegangen werden, dass diese Verlangsamung auch im Falle des OSGi Security Layers auftreten kann. Auch CICS Services kommen nicht ohne Nachteile, denn sollte eine Anwendungen diese tatsächlich verwenden, ist einer der wichtigsten Vorteile von Java, die Platformunabhängigkeit, nicht mehr gegeben, da stets CICS als Middleware für die Anwendung vorausgesetzt wird. Es bleibt jedoch abzuwarten welche Entwicklungen im Bereich des OSGi Frameworks zukünftig erfolgen werden. Ein spekulativer Ansatz zur Lösung der vorgestellten Defizite wird in einer parallel im Informatik Spektrum erscheinenden Veröffentlichung [Har12-b] beschrieben.[R.H.1] Ein vielversprechender nicht spekulativer Ansatz, erwähnt in einem frühen Entwurf der aktuellen OSGi Framework Spezifikation (siehe [OSG10]), beschreibt die Isolation von Bundles durch Erstellung mehrerer sogenannter „Nested Frameworks“. Diese sind komplett voneinander isoliert und kommunizieren nur über standardisierte Schnittstellen miteinander und könnten somit unter Umständen als Alternative zum OSGi Security Layer dienen. 1. Literatur [Aye07] N. Ayewah, W. Pugh, J. D. Morgenthaler, J. Penix, Y. Zhou, Evaluating Static Analysis Defect Warnings On Production Software. In: Proceedings of the 7th ACM SIGPLAN-SIGSOFT workshop on Program analysis for software tools and engineering, PASTE ’07, S. 1–8, New York, NY, USA, 2007. ACM. http://findbugs.cs.umd.edu/papers/FindBugsExperiences07.pdf [Bal97] D. Balfanz, L. Gong, Experience with Secure Multi-Processing in Java. Technical report, Department of Computer Science, Princeton University September 1997. http://sip.cs.princeton.edu/pub/icdcs.pdf [Chi09] R. Chinnici, B. Shannon, Java Platform, Enterprise Edition (JavaEE) Specification, v6, October 2009. http://download.oracle.com/otndocs/jcp/javaee- 6.0fr-oth-JSpec/ [Cza00] G. Czajkowski, Application Isolation in the Java Virtual Machine. In: Proceedings of the 15th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications. New York : ACM Press, 2000, S. 354–366. http://research.sun.com/projects/barcelona/papers/oopsla00.pdf [Din04] A. Dingle. Reclaiming Garbage and Education: Java Memory Leaks. J. Comput. Small Coll., 20:8 - 16, Dezember 2004 [IBM] IBM Corp, IBM Monitoring and Diagnostic Tools for Java - Health Center Version 2.0. Webseite. http://www.ibm.com/developerworks/java/jdk/tools/healthcenter/ [IBM01] IBM Corp, New IBM Technology featuring Persistent Reusable Java Virtual Machines, Oktober 2001. http://www03.ibm.com/systems/resources/servers_eserver_zseries_software_java_pdf_prjvm13 .pdf [IBM11-a] IBM Corp, CICS Transaction Server for z/OS Version 4 Release 2: Upgrading from CICS TS Version 3.1, 2011. http://publib.boulder.ibm.com/infocenter/cicsts/v4r2/topic/com.ibm.cics.ts.migration.do c/dfheg_pdf.pdf [IBM11-b] IBM Corp, Java Applications in CICS (Version 4 Release 2), 2011. http://publib.boulder.ibm.com/infocenter/cicsts/v4r2/topic/com.ibm.cics.ts.java.doc/dfh pj_pdf.pdf [IBM11-c] IBM Corp, Techreport: History of CICS. Webseite, 2011. https://www304.ibm.com/support/docview.wss?uid=swg21025234 [Gra93] J. Gray, A. Reuter, Transaction Processing. Morgan, Kaufman, 1993 [Fow00] M. Fowler, Webseite, 2000. http://www.martinfowler.com/bliki/POJO.html [Fri02] G. Friesen. Java 2 by Example. Que, Indianapolis, IN, 2nd edition, 2002 [Har12-a] R. Harbach, CICS JVM Server Application Isolation. Masterarbeit am Wilhelm-Schickard-Institut für Informatik der Universität Tübingen, März 2012 [Har12-b] R. Harbach, W. Rosenstiel, W. Spruth, Isolation in Java Transaktionen, INFORMATIK SPEKTRUM Veröffentlichung erscheint demnächst. [Her05] A. Herzog, N. Shahmehri, Performance of the Java security manager. Computers & Security, 24(3):192 – 207, 2005. http://rewerse.eu/publications/download/REWERSE- RP- 2005- 141.pdf [Lin99] T. Lindholm, F. Yellin. The Java Virtual Machine Specification. AddisonWesley Longman Publishing Co., Inc., Boston, MA, USA, 2nd ed edition, 1999. http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html [Lip08] M. Lippert. Classloading and Type Visibility in OSGi. Presentation slides, 2008. http://www.martinlippert.org/events/WJAX2008ClassloadingTypeVisibilityOSGi.pdf [Mcg99] G. McGraw, E. Felden. Securing Java. John Wiley & Sons, Inc., Januar 1999. http://www.securingjava.com [Moe93] Hanspeter Mössenböck. Objektorientierte Programmierung. Springer, 1993, ISBN 3-540-55690-7 [Mue05] J. Mueller, Anwendungs- und Transaktionsisolation unter Java, Mai 2005. http://www-ti.informatik.uni-tuebingen.de/~spruth/DiplArb/jmueller.pdf [Nyl99] J. Nylund. Memory Leaks in Java Programs. Application Development Trends, Dezember 1999. http://adtmag.com/articles/1999/12/24/memory-leaks-injava-programs.aspx [OSG10] OSGi Alliance, Version 4.3 Core Early Draft 1, April 2010. http://www.osgi.org/download/osgi- core-4.3-early-draft1.pdf [OSG11b] OSGi Alliance, OSGi Service Platform Core Specification Release 4 Version 4.3, April 2011. http://www.osgi.org/download/r4v41/r4.core.pdf [Par09] P. Parrend, S. Frénot, Security benchmarks of OSGi platforms: towards Hardened OSGi. Softw. Pract. Exper., 39:471–499, April 2009 [Ray11] C. Rayns, S. Bertram, G. Bogner, C. Carlin, A. Clark, A. Ferrell, G. Keehn, P. Klein, R. Lee, E. Woerner, CICS Transaction Server from Start to Finish. IBM International Technical Support Organization (ITSO), December 2011. http://www.redbooks.ibm.com/redbooks/pdfs/sg247952.pdf [Rep04] T. Reps, M. Sagiv, R. Wilhelm, Static Program Analysis via 3-Valued Logic. In Ra jeev Alur and Doron Peled, editors, Computer Aided Verification, volume 3114 of Lecture Notes in Computer Science, S. 401–404. Springer Berlin / Heidelberg, 2004. http://groups.csail.mit.edu/cag/crg/papers/reps04shape.pdf [San04] B. Sandén, Coping with Java Threads. IEEE Computer, Vol. 37, Nr. 4, April 2004, S. 20 [She99] L. Sheng, The Java Native Interface: Programmer’s Guide and Specification. Java series. Addison-Wesley, Reading, MA, 1999. http://java.sun.com/docs/books/jni/download/jni.pdf Alle in digitaler Form verfügbaren Aufsätze sind zusätzlich in einem Mirror unter http://www-ti.informatik.uni-tuebingen.de/~spruth/Mirror/Java_Spektrum/index.html abrufbar.