PatentDe  


Dokumentenidentifikation DE60018505T2 13.04.2006
EP-Veröffentlichungsnummer 0001056013
Titel Vertraute Überprüfung von Rechnerprogrammodulen
Anmelder Sun Microsystems, Inc., Palo Alto, Calif., US
Erfinder Bracha, Gilad, Los Altos, US;
Liang, Sheng, Cupertino, US;
Lindholm, Timothy G., Palo Alto, US
Vertreter Betten & Resch, 80333 München
DE-Aktenzeichen 60018505
Vertragsstaaten DE, FR, GB, IE, SE
Sprache des Dokument EN
EP-Anmeldetag 22.05.2000
EP-Aktenzeichen 003043197
EP-Offenlegungsdatum 29.11.2000
EP date of grant 09.03.2005
Veröffentlichungstag im Patentblatt 13.04.2006
IPC-Hauptklasse G06F 11/36(2006.01)A, F, I, 20051017, B, H, EP

Beschreibung[de]
Querverweis auf zugehörige Anmeldungen

Diese Anmeldung ist bezogen auf die US-Patentanmeldung mit der seriellen Nr. 575,291 (P1000), eingereicht am 20. Dezember 2995, Yellin und Gosling, mit dem Titel BYTECODE PROGRAM INTERPRETER APPARATUS AND METHOD WITH PREVERIFICATION OF DATA TYPE RESTRICTIONS AND OBJECT INITALIZATION, die nun das US-Patent Nr. 5,740,441 ist; und die US-Patentanmeldung mit der seriellen Nr. 09/134,477 (P3135), eingereicht am 14. August, 1998; Bracha und Liang, mit dem Titel METHODS AND APPARATUS FOR TYPE SAFE, LAZY, USER-DEFINED CLASS LOADING.

Diese Anmeldung ist auch bezogen auf die US-Patentanmeldung mit der seriellen Nr. 09/321,223 [50553-228] (P3564), eingereicht am 27. Mai 1999, mit dem Titel FULLY LAZY LINKING; die US-Patentanmeldung mit der seriellen Nr. 09/320,574 [50253-229] (P3565), eingereicht am 27. Mai 1999 mit dem Titel MODULE-BY-MODULE VERIFICATION; die US-Patentanmeldung mit der seriellen Nr. 09/321,226 [50253-230] (P3566), eingereicht am 27. Mai 1999, mit dem Titel FULLY LAZY LINKING WITH MODULE-BY-MODULE VERIFICATION; und die US-Patentanmeldung mit der seriellen Nr. 09/321,228 [50253-236] (P3809), eingereicht am 27. Mai 1999, mit dem Titel DATAFLOW ALGORITHM FOR SYMBOLIC COMPUTATION OF LOWEST UPPER BOUND TYPE.

Gebiet der Erfindung

Diese Erfindung betrifft allgemein Computerprogrammiersprachen, und insbesondere Computerprogrammiersprachen mit einem dynamischen Binden, die Anweisungen verifizieren, während sie ein träges Laden unterstützen.

Beschreibung des zugehörigen Standes der Technik

Im Allgemeinen werden Computerprogramme als Quellcode- bzw. Quellsprachenangaben in einer problemorientierten bzw. höheren Sprache geschrieben, die für einen Menschen einfach zu verstehen ist. Wenn die Computerprogramme tatsächlich ausgeführt werden, reagiert ein Computer auf einen Maschinencode, der aus Anweisungen besteht, die aus binären Signalen bestehen, die den Betrieb einer Zentralverarbeitungseinheit (CPU) direkt steuern. Es ist im Stand der Technik wohlbekannt, ein spezielles Programm zu verwenden, das Compiler genannt wird, um den Quellcode bzw. die Quellsprache zu lesen und um seine bzw. ihre Angaben in die Maschinencode- bzw. Maschinensprachenanweisungen der spezifischen CPU umzuwandeln. Die so erzeugten Maschinencodeanweisungen sind plattformabhängig, d.h. unterschiedliche Computervorrichtungen haben unterschiedliche CPUs mit unterschiedlichen Anweisungsgruppen, die durch unterschiedliche Maschinencodes angezeigt werden.

Es ist im Stand der Technik auch bekannt, mächtigere bzw. leistungsfähigere Programme durch Kombinieren von mehreren einfacheren Programmen zu bilden. Diese Kombination kann durch Kopieren von Segmenten eines Quellcodes miteinander vor einem Kompilieren und dann durch Kompilieren der kombinierten Quelle durchgeführt werden. Wenn ein Segment von Quellcodeangaben häufig ohne Änderungen verwendet wird, ist es oft vorzuziehen, es einmal für sich selbst zu kompilieren, um ein Modul zu erzeugen, und das Modul mit anderen Modulen nur dann zu kombinieren, wenn diese Funktion tatsächlich benötigt wird. Dieses Kombinieren von Modulen nach einer Kompilation wird Binden genannt. Wenn die Entscheidung darüber, welche Module zu kombinieren sind, von Laufzeitbedingungen abhängt, und die Kombination der Module zu einer Laufzeit genau vor einer Ausführung erfolgt, wird das Binden dynamisches Binden genannt.

Ein Vorteil eines Bindens besteht darin, dass Programme für ein Modul gleichzeitig entwickelt werden können und eine Produktivität verbessert werden kann, da verschiedene Entwickler, möglicherweise an unterschiedlichen Orten, gleichzeitig an separaten Modulen arbeiten.

Ein Vorteil eines zu einer Laufzeit durchgeführten Bindens, das heißt eines dynamischen Bindens, wenn das Programm gerade ausgeführt wird, besteht darin, dass Module, die während einer Ausführung nicht verwendet werden, nicht gebunden werden müssen, wodurch die Anzahl von Operationen reduziert wird, die ausgeführt werden müssen, und wodurch möglicherweise die Größe des ausführenden Codes reduziert wird. Allgemein müssen Module geladen, d.h. identifiziert und in einen Speicher gebracht werden, bevor sie gebunden werden. Das verzögerte Binden von Modulen, bis das Modul benötigt wird, lässt ebenso eine Verzögerung bezüglich eines Ladens dieser Module zu, was träges Laden genannt wird.

Beim Zusammenbauen von mehreren Modulen, die unabhängig geschrieben worden sein können, ist es vernünftig, sowohl zu prüfen, dass jedes Modul innerhalb seiner eigenen vier Ecken richtig durchführt, d.h. mit Innenmodulprüfungen, als auch zu prüfen, dass die Module richtig miteinander arbeiten, d.h. mit Zwischenmodulprüfungen. Durch eine Analogie zu der Terminologie, die durch die Entwickler der Programmiersprache JAVATM verwendet wird, kann dieses Prüfen eines Moduls nach einer Kompilation Verifizierung genannt werden.

Ein Beispiel für eine Computerarchitektur, die einen Vorteil aus einem dynamischen Binden zieht, ist eine virtuelle Maschine (VM), wie beispielsweise die virtuelle Maschine JAVATM (JVM) von Sun Microsystems, Inc., welche eine abstrakte Computerarchitektur ist, die in Hardware oder Software implementiert sein kann. Jede Implementierung soll in den folgenden Beschreibungen einer VM enthalten sein.

Eine VM kann eine Plattformunabhängigkeit auf die folgende Weise zur Verfügung stellen. Angaben, die in einer problemorientierten bzw. höheren Computersprache ausgedrückt werden, wie beispielsweise der Programmiersprache JAVATM, werden in VM-Anweisungen kompiliert, die systemunabhängig sind. Die VM-Anweisungen sind für die VM, was ein Maschinencode für eine Zentralverarbeitungseinheit (CPU) ist. Die VM-Anweisungen können dann von einer Maschine zu einer anderen transferiert werden. Jeder andere Prozessor benötigt seine eigene Implementierung einer VM. Die VM lässt die VM-Anweisungen durch Übersetzen oder Interpretieren der VM-Anweisungen mit einer oder mit mehreren Anweisungen gleichzeitig laufen. Bei vielen Implementierungen ist die VM-Implementierung ein Programm, das auf der CPU eines bestimmten Computers läuft, aber die VM-Anweisungen können auch als die ursprüngliche Anweisungsgruppe eines bestimmten Prozessors oder einer bestimmten Vorrichtung verwendet werden. Im letzteren Fall ist die VM eine "aktuelle" Maschine. Andere Operationen können auch durch die VM durchgeführt werden, einschließlich eines dynamischen Bindens und einer Verifizierung.

Der Prozess eines Programmierens unter Verwendung einer solchen VM hat dann zwei zu ihm gehörige Zeitepochen; "Kompilierzeit" bezieht sich auf die Schritte, die die höhere Sprache in die VM-Anweisungen umwandeln, und "Laufzeit" bezieht sich auf die Schritte, die in einer JAVATM-VM-Umgebung Anweisungen interpretieren, um das Modul auszuführen. Zwischen einer Kompilierzeit und einer Laufzeit können die Module von Anweisungen, die aus Angaben kompiliert sind, für erweiterte, beliebige Zeitperioden daheim sitzen oder können von einer Speichervorrichtung zu einer anderen transferiert werden, einschließlich eines Transfers über ein Netzwerk.

Die Probleme, auf die bei einem Versuch getroffen werden, ein dynamisches Binden mit einer Verifizierung und mit oder ohne einem trägen Laden zu implementieren, können für das Beispiel der virtuellen Maschine JAVATM dargestellt werden. Die JVM ist eine bestimmte VM für die objektorientierte höhere Programmiersprache JAVATM, die dafür entwickelt ist, ein dynamisches Binden, eine Verifizierung und ein träges Laden durchzuführen, wie es für die herkömmliche JVM in The JAVATM Virtual Machine Specification, von T. Lindholm und Frank Yellin, Addison-Wesley, Menlo Park, Kalifornien 1997, beschrieben ist.

Objektorientierte Programmiertechniken wie beispielsweise diejenigen, die durch die JAVATM-Plattform verwendet werden, werden weithin verwendet. Die Basiseinheit von objektorientierten Programmen ist das Objekt, das Verfahren (Prozeduren) und Felder (Daten) hat, die hierin Elemente genannt werden. Objekte, die Elemente gemeinsam nutzen, sind in Klassen gruppiert. Eine Klasse definiert die gemeinsam genutzten Elemente der Objekte in der Klasse. Jedes Objekt ist dann ein besonderer Fall der Klasse, zu welcher es gehört. In der Praxis wird eine Klasse oft als Schablone zum Erzeugen von mehreren Objekten (mehreren Fällen) mit gleichen bzw. ähnlichen Merkmalen verwendet.

Eine Eigenschaft von Klassen ist eine Einkapselung, welche die Eigenschaft beschreibt, dass die aktuelle Implementierung der Elemente innerhalb der Klasse vor einem außen stehenden Anwender versteckt ist, und vor anderen Klassen, außer einer solchen, wie sie durch eine Schnittstelle freigelegt ist. Dies macht Klassen für eine verteilte Entwicklung geeignet, wie beispielsweise durch verschiedene Entwickler an verschiedenen Orten an einem Netzwerk. Ein vollständiges Programm kann durch Zusammenbauen der Klassen gebildet werden, die benötigt werden, durch Binden von ihnen miteinander und durch Ausführen des resultierenden Programms.

Klassen genießen die Eigenschaft der Vererbung. Vererbung ist ein Mechanismus, der einer Klasse ermöglicht, alle der Elemente einer anderen Klasse zu erben. Die Klasse, die von einer anderen Klasse erbt, wird Unterklasse genannt. Die Klasse, die die Attribute zur Verfügung stellt, ist die Superklasse. Symbolisch kann dies geschrieben werden als Unterklasse <= Superklasse oder Superklasse => Unterklasse. Die Unterklasse kann die Fähigkeiten der Superklasse durch Hinzufügen von zusätzlichen Elementen erweitern. Die Unterklasse kann ein Attribut der Superklasse durch Bereitstellen eines Ersatzelements mit demselben Namen und demselben Typ überschreiben.

Die JVM arbeitet in einem bestimmten binären Format für die kompilierten Klassen – dem Klassendateienformat. Eine Klassendatei enthält JVM-Anweisungen und eine Symboltabelle, sowie andere untergeordnete Information. Der Sicherheit halber erlegt die JVM den Anweisungen in einer Klassendatei strenge Format- und Strukturbeschränkungen auf. Bei einem bestimmten Beispiel sind JVM-Anweisungen typenspezifisch, die an Operanden arbeiten sollen, die von einem gegebenen Typ sind, wie es nachfolgend erklärt wird. Ähnliche Beschränkungen könnten durch jede VM auferlegt werden. Für jede Sprache mit einer Funktionalität, die in Bezug auf eine gültige Klassendatei ausgedrückt werden kann, kann die JVM ein Host sein. Die Klassendatei ist entwickelt, um objektorientierte Strukturen zu handhaben, die Programme darstellen können, die in der Programmiersprache JAVATM geschrieben sind, aber kann auch mehrere andere Programmiersprachen unterstützen.

In der Klassendatei ist eine Variable eine Speicherstelle, zu der ein Typ gehört, der manchmal ihr Kompilierzeittyp genannt wird, der entweder ein Grundelementen- oder ein Referenztyp ist. Die Referenztypen sind Zeiger zu Objekten oder eine spezielle Nullreferenz, die sich auf kein Objekt bezieht. Vom Typ einer Unterklasse wird gesagt, dass er ein Untertyp von seiner Superklasse ist. Die Grundelemententypen für die JVM enthalten einen Bool'schen Typ (der die Wahrheitswerte wahr und falsch annimmt), char (Code für ein Unicode-Zeichen), Byte (was acht Bits von 0 oder 1 bezeichnet), kurz (was eine kurze ganze Zahl bezeichnet), int (was eine ganze Zahl bezeichnet), lang (was eine lange ganze Zahl bezeichnet), gleitend (Gleitkommazahl mit einfacher Genauigkeit) oder doppelt (Gleitkommazahl mit doppelter Genauigkeit).

Die Elemente eines Klassentyps sind Felder und Verfahren; diese enthalten Elemente, die von der Superklasse geerbt sind. Die Klassendatei benennt auch die Superklasse. Ein Element kann öffentlich sein, damit darauf durch Elemente von irgendeiner Klasse zugegriffen werden kann. Auf ein privates Element kann nur durch Elemente der Klasse zugegriffen werden, die seine Deklaration enthält. Auf ein geschütztes Element kann durch Elemente der deklarierenden Klasse oder von irgendwo in dem Paket, in welchem es deklariert wird, zugegriffen werden. In der Programmiersprache JAVATM können Klassen gruppiert werden, und die Gruppe kann benannt werden; die benannte Gruppe von Klassen ist ein Paket.

Die aktuellen bzw. tatsächlichen Anweisungen für die JVM sind innerhalb von Verfahren der Klasse enthalten, die durch die Klassendatei codiert ist.

Wenn ein JAVATM-Sprachenprogramm Beschränkungen einer Operation verletzt, erfasst die JVM einen ungültigen Zustand und signalisiert diesen Fehler zu dem Programm als Ausnahme. Von einer Ausnahme wird gesagt, dass sie von der Stelle (aus-)geworfen wird, wo sie auftrat, und es wird von ihr gesagt, dass sie an der Stelle gefangen wird, zu welcher eine Steuerung transferiert wird. Jede Ausnahme wird durch einen Fall der Klasse auswerfbar oder von einer ihrer Unterklassen dargestellt; ein solches Objekt kann dazu verwendet werden, Information von der Stelle an, bei welcher eine Ausnahme auftritt, zu einem Teil des Programms, einer Ausnahmehandhabungseinheit, die sie fängt und sie behandelt, zu tragen.

Die JVM startet eine Ausnahme durch Aufrufen des Verfahrens "Haupt" von irgendeiner spezifizierten Klasse, was ihr ein einzelnes Argument übergibt, welches eine Anordnung von Ketten ist. Dies veranlasst, dass die spezifizierte Klassen geladen, gebunden und initialisiert wird.

Laden bezieht sich auf den Prozess zum Finden der binären Form einer Klasse oder eines Pakets mit einem bestimmten Namen, und zwar typischerweise durch Wiedergewinnen bzw. Auslesen einer binären Darstellung, die zuvor aus einem Quellcode kompiliert ist. In der JVM gewinnt der Ladeschritt die Klassendatei wieder, die die erwünschte Klasse darstellt. Der Ladeprozess ist durch den Urlade-Klassenlader oder einen anwenderdefinierten Klassenlader implementiert. Ein anwenderdefinierter Klassenlader ist selbst durch eine Klasse definiert. Ein Klassenlader kann eine bestimmte Sequenz von Stellen anzeigen, um zu suchen, um die Klassendatei zu finden, die eine benannte Klasse darstellt. Ein Klassenlader kann binäre Darstellungen von Klassen in einen Cache laden, wobei er sie basierend auf einer erwarteten Anwendung im Voraus holt, oder eine von zugehörigen Klassen miteinander laden. Je mehr Klassen im Voraus geholt werden oder in einer Gruppe geladen werden, um so "eifriger" ist der Lader. Ein "träger" Lader holt so wenig Klassen wie möglich im Voraus oder gruppiert sie. Die herkömmliche JVM-Spezifikation lässt ein breites Spektrum von Ladeverhalten zwischen eifriger und nahezu vollständig träge zu.

Eine VM ist vollständig träge, wenn sie einen Klassenlader aufruft, um nur eine Klasse zu der Zeit zu laden, zu welcher die Klasse zuerst nötig ist, um eine Anweisung einer Klasse auszuführen, die gegenwärtig verarbeitet wird. Ein vollständig träges Laden verschwendet dann, wenn es erreicht wird, keine Laufzeitbetriebsmittel, wie beispielsweise einen Systemspeicher und eine Ausführungszeit, während Klassen geladen werden, die zur Laufzeit nicht streng erforderlich sind.

Ein Binden in der JVM ist der Prozess zum Annehmen einer binären Form einer Klasse in einem Speicher und zum Kombinieren von ihr in den Laufzeitzustand einer VM, so dass sie ausgeführt werden kann. Eine Klasse muss geladen werden, bevor sie gebunden werden kann. Drei unterschiedliche Aktivitäten sind gemäß der JVM-Spezifikation am Binden beteiligt: eine Verifizierung, eine Vorbereitung und eine Auflösung von symbolischen Referenzen.

Während einer Verifizierung werden nötige Beschränkungen bezüglich einer binären Klasse im Klassendateienformat geprüft. Dies ist für die Sicherheitsvorkehrungen der JVM fundamental. Eine Verifizierung stellt sicher, dass keine illegalen bzw. ungesetzlichen bzw. unerlaubten Operationen durch die JVM versucht werden, die zu sinnlosen Ergebnissen führen können oder die die Integrität des Betriebssystems, des Dateiensystems oder der JVM selbst kompromittieren können. Jedoch erfordert ein Prüfen dieser Beschränkungen manchmal eine Kenntnis über Beziehungen bezüglich eines Untertyps unter anderen Klassen; somit hängt eine erfolgreiche Verifizierung typischerweise von den Eigenschaften von anderen Klassen ab, auf die durch die Klasse Bezug genommen wird, die gerade verifiziert wird. Dies hat den Effekt, dass die gegenwärtige JVM-Entwicklungsspezifikation für einen Verifizierungszusammenhang empfindlich gemacht ist.

Die binären Klassen der JVM sind im Wesentlichen Exemplare von allgemeinen Programmmodulen, die Anweisungen enthalten, die aus kompilierten Quellenangaben erzeugt sind. Eine Kontextempfindlichkeit von Gültigkeitsprüfungen bedeutet, dass diese Prüfungen von Information abhängen, die über mehr als ein Modul ausgebreitet ist, d.h. diese Prüfungen werden hierin Quermodulprüfungen oder Zwischenmodulprüfungen genannt. Gültigkeitsprüfungen, die keine Information von einem anderen Modul erfordern, werden hierin Innenmodulprüfungen genannt.

Eine kontextempfindliche Verifizierung hat einige Nachteile. Beispielsweise führt sie in einem objektorientierten Programmiersystem, wie der JAVATM-Plattform, zu einem Verifizierer, der ein Laden einer Klasse initiiert, wenn der Verifizierer Untertypbeziehungen unter Klassen prüfen muss, die nicht bereits geladen sind. Ein solches Laden kann selbst dann erfolgen, wenn der Code, der auf die anderen Klassen Bezug nimmt, nicht einmal ausgeführt wird. Das bedeutet, dass die kontextempfindliche Verifizierung ein vollständig träges Laden stören kann. Deshalb kann ein Laden im Vergleich mit einem Prozess, der die Klassen so lange nicht lädt, bis auf sie durch die Anweisungen Bezug genommen wird, die tatsächlich ausgeführt werden, Speicher verbrauchen und zur Laufzeit langsam ausführen.

Wenn eine Verifizierung kontextempfindlich ist, gibt es kein Vorsehen einer Verifizierung von einer Klasse oder einem Modul zu einer Zeit vor einer Laufzeit. Dies ist ein Nachteil, weil Klassen nicht vor einer Zeit, z.B. vor einer Laufzeit, verifiziert werden können, so dass eine Verifizierung immer auf Kosten der Laufzeit erfolgen muss. Somit gibt es eine Notwendigkeit für eine Modul-für-Modul-Verifizierung, die auch Modul-zu-einer-Zeit-Verifizierung genannt wird, vor einer Laufzeit. Eine solche Verifizierung wird hierin Verifizierung im Voraus genannt, weil sie technisch unterschiedlich von der Verifizierung ist, die während einer Laufzeit erfolgt, und zwar bindend durch die JVM.

Ebenso wird deshalb, weil eine Verifizierung zur Laufzeit durchgeführt wird, eine Klasse, die einmal in Betrieb genommen worden ist und durch eine Verifizierung geführt worden ist, wieder jedes Mal einer Verifizierung unterzogen, wenn die Klasse geladen wird – selbst wenn die Klasse gerade bei derselben Anwendung auf demselben Hostcomputer verwendet wird, wo keine neue Verifizierungsausgaben wahrscheinlich sind oder wo eine Situation so eingerichtet sein kann, dass keine Änderungen, die eine Verifizierung beeinflussen würden, durchgeführt werden können. Dies kann zu einer redundanten Verifizierung führen, wodurch mehr Speicher erforderlich wird und ein Ausführen während einer Laufzeit langsamer erfolgt, als es nötig sein sollte. Somit gibt es eine Notwendigkeit für eine Option zum Verwenden von im Voraus verifizierten Modulen ohne eine weitere, oder mit einer minimalen, Verifizierung zur Laufzeit.

Die Notwendigkeiten für eine Vorverifizierung und ein vollständig träges Laden sind separate Notwendigkeiten, die separat erfüllt werden könnten. Es gibt auch eine Notwendigkeit zum Unterstützen einer Modul-für-Modul-Vorverifizierung zusammen mit einem vollständig trägen Laden.

Die Notwendigkeit für eine Vorverifizierung, einschließlich einer Reduzierung einer Laufzeitverifizierung, kann im Konflikt mit den Zielen für eine Sicherheit sein, die erfordern, dass alle Module, die einer virtuellen Maschine oder irgendeiner Computerarchitektur zugeführt werden, zur Laufzeit geprüft werden, um illegale oder schädigende Operationen zu verhindern. Beispielsweise kann es in einer nicht vertrauenswürdigen Situation, wie beispielsweise bei einem Herunterladen eines Moduls und seiner Vorverifizierungsausgabe aus dem Internet, sein, dass ein Angreifer die Vorverifizierungsausgabe beschwindeln bzw. parodieren kann – was möglicherweise veranlasst, dass eine bösartige Klasse gutartig erscheint. Somit gibt es eine Notwendigkeit für eine Vorverifizierung, die in nicht vertrauenswürdigen Situationen verwendbar ist, wie bei einem Herunterladen von Modulen über das Internet.

Die Notwendigkeit für ein vollständig träges Laden oder eine Modul-für-Modul-Vorverifizierung erzeugt eine Notwendigkeit für eine Ersatzdarstellung eines Typengitters. Ein Typengitter ist eine mathematische Struktur, die Untertypbeziehungen zwischen Typen ausdrückt. Eine Darstellung eines Typengitters ist durch die JVM zum Anzeigen der Typen und Untertypen von Klassen während einer Laufzeit gebildet. Die JVM unterhält auch Referenzen und Typen von allen Attributen der Klasse, die gebunden werden. Es wird erwartet, dass gleiche Laufzeitstrukturen für irgendeinen dynamischen Bindeprozess nützlich sind. Zum Unterstützen einer Klasse-für-Klasse-Vorverifizierung oder eines vollständig trägen Ladens muss eine Typenprüfung ohne vollständige Kenntnis über das Typengitter durchgeführt werden, wovon das Meiste typischerweise in anderen Modulen definiert ist, für die es sein kann, dass sie sonst noch nicht geladen werden müssen. Insbesondere muss die JVM typischerweise einen LUB-(niedrigste obere Grenze)-Typ in dem Typengitter während einer Verifizierung finden. Somit gibt es eine Notwendigkeit zum Durchführen der Funktionen, die auf einer LUB beruhen, selbst wenn das Typengitter nicht verfügbar ist.

Zusammenfassung der Erfindung

Die vorangehenden und andere Merkmale, Aspekte und Vorteile der vorliegenden Erfindung werden aus der folgenden detaillierten Beschreibung der vorliegenden Erfindung klarer werden, wenn sie in Zusammenhang mit den beigefügten Zeichnungen genommen wird.

Es ist eine Aufgabe der Erfindung, eine Verifizierung während einem Binden zu unterstützen, während für ein vollständig träges Laden gesorgt wird. Es wäre für einen dynamischen Binder, und insbesondere die JVM, vorteilhaft, zu verlangen, dass die gesamte Auflösung von Modulen (z.B. Klassen), auf die Bezug genommen wird, bei spezifischen, definierten Stellen während einer Ausführung von Anweisungen (z.B. von einem Verfahren) träge durchgeführt werden würde. Die Vorteile enthalten:

  • • Charakteristiken für einmal Schreiben, Laufen zu jeder Zeit (WORA = write once, run anytime) werden verbessert. Das Verhalten eines Programms in Bezug auf Bindefehler ist auf allen Plattformen und bei allen Implementierungen dasselbe.
  • • Die Testbarkeit wird stark verbessert. Beispielsweise muss man nicht alle Stellen vorwegnehmen, wo eine Klasse oder ein Verfahren gebunden werden könnte, und versuchen, Ausnahmen bei all diesen Stellen in einem Fall zu fangen, in welchem die Klasse oder das Verfahren nicht gefunden werden kann.
  • • Anwender können das Vorhandensein von Modulen auf eine zuverlässige und einfache Weise bestimmen. Beispielsweise kann der Anwender Bindefehler aufgrund von Aufrufen zu Modulen vermeiden, die bei einer anderen Version einer Laufzeitumgebung fehlen, indem diese Referenzen auf einem Programmzweig platziert werden, der solange nicht ausgeführt wird, bis die andere Version verfügbar ist.

Der Umfang der Ladeverhaltensweisen der herkömmlichen JVM-Spezifikation lässt diese Vorteile nicht zu.

Es ist eine weitere Aufgabe der vorliegenden Erfindung, eine Vorverifizierung für Ein-Modul-zu-einer-Zeit zu unterstützen. Es ist auch eine Aufgabe der vorliegenden Erfindung, vorverifizierte Anweisungen zu verwenden, um eine Laufzeitverifizierung zu reduzieren. Einige Anwender der JAVATM-Plattform würden wünschen, kontextunempfindliche oder kontextunabhängige Verifizierungsprüfungen an einigen Klassen durchzuführen. Es gibt eine Anzahl von Vorteilen für eine kontextunabhängige Prüfung, welche während oder nach einer Kompilation und vor einer Laufzeit durchgeführt werden kann. Die Vorteile enthalten:

  • • Einige Verifizierungsfehler können vor einer Laufzeit erfasst werden;
  • • Die bindende Komponente einer Laufzeit, wenn noch eine erforderlich ist, ist kleiner und einfacher, weil das Ausmaß eines Verifizierungscodes, den sie enthält, reduziert ist; und
  • • Der Anwender kann Module (in einem gesicherten Verwahrungsort, wie beispielsweise einem RDBMS (Bezugs-Datenbankmanagementsystem)) eher auf einer Modul-für-Modul-Basis als Anwendung für Anwendung speichern, und soviel Arbeit wie möglich vor einer Laufzeit durchführen. Dies vermeidet eine redundante Verifizierung und reduziert oder eliminiert Laufzeitkosten für eine Verifizierung.

Es ist eine weitere Aufgabe der vorliegenden Erfindung, eine Vorverifizierung für Ein-Modul-(oder Klasse)-zu-einer-Zeit mit einer Laufzeitverifizierung zu unterstützen, die ein vollständig träges Laden zulässt, um die Vorteile von beidem gleichzeitig zu genießen.

Es ist eine weitere Aufgabe der vorliegenden Erfindung, Module von nicht vertrauenswürdigen Quellen im Voraus zu verifizieren, um den Schutzumfang von Situationen zu erhöhen, in welchem die Vorteile einer Vorverifizierung gelten.

Es ist eine weitere Aufgabe der vorliegenden Erfindung, einen Ersatz für eine LUB zu verwenden, wenn eine vollständige Kenntnis über das Typengitter fehlt, um Zwischenmodul-Gültigkeitsprüfungen zu vereinfachen.

Das Dokument "Proof linking: An Architecture for Modular Verification of Dynamically-Linked Mobile Code" von Philip W.L. Fong und Robert D. Cameron, School of Computing Science, Simon Fraser University, B.C., Kanada (XP-000831185) offenbart eine Standardarchitektur zum Fertigen von mobilen Codeverifizierern basierend auf dem Konzept eines Versuchsbindens. Nicht vertrauenswürdige Kompilationseinheiten werden nach einem Laden einer statischen Verifizierung unterzogen. Wo eine Kenntnis über eine andere Kompilationseinheit erforderlich ist, verifiziert der Verifizierer die andere Einheit nicht, sondern berechnet statt dessen einen Sicherheitsvorzustand, der die Sicherheit der Kompilationseinheit garantieren wird, vor einem Durchlassen bzw. Übergeben des verifizierten Codes zu der Laufzeitumgebung.

Gemäß der vorliegenden Erfindung ist ein Verfahren für eine vertrauenswürdige Verifizierung von Anweisungen in einem Modul eines Computerprogramms gemäß Anspruch 1 zur Verfügung gestellt.

Es ist weiterhin ein Computerprogrammprodukt für eine vertrauenswürdige Verifizierung von Anweisungen in einem Modul eines Computerprogramms gemäß Anspruch 7 zur Verfügung gestellt.

Es ist weiterhin eine vertrauenswürdige Verifizierervorrichtung für eine vertrauenswürdige Verifizierung von Anweisungen in einem Modul eines Computerprogramms gemäß Anspruch 12 und eine Signalübertragung gemäß Anspruch 13 zur Verfügung gestellt.

Kurze Beschreibung der Zeichnungen

Die Aufgaben, Merkmale und Vorteile des Systems der vorliegenden Erfindung werden aus der folgenden Beschreibung klar werden, wobei:

1A eine Ansicht eines beispielhaften Computersystems ist, das zur Verwendung beim Ausführen der Erfindung geeignet ist.

1B ein Blockdiagramm einer beispielhaften Hardwarekonfiguration des Computers der 1A ist.

1C eine Darstellung eines beispielhaften Speichermediums ist, das zum Speichern eines Programms und von Dateninformation gemäß der Erfindung geeignet ist.

1D ein Blockdiagramm einer Netzwerkarchitektur ist, die zum Tragen von Daten und Programmen gemäß der Erfindung geeignet ist.

1E ein Blockdiagramm eines Computers ist, der gemäß der Erfindung konfiguriert ist.

2 ein Beispiel einer Klasse BAR mit einem Verfahren FOO unter Bezugnahme auf Klassen A und B in der Pseudosprache gleich der JAVATM-Programmiersprache ist.

3 ein Ablaufdiagramm ist, das ein vollständig eifrigeres Laden der Beispielklasse BAR aus 2 ist.

4A ein Ablaufdiagramm ist, das ein nahezu träges Laden der Beispielklasse BAR aus 2 ist.

4B ein Ablaufdiagramm ist, das ein Prüfen vom Zugriffstyp zeigt, das bei einem letzten Update für die JVM für einen Schritt 475 des in 4A gezeigten nahezu trägen Ladens verwendet wird.

5A ein Ablaufdiagramm ist, das eine Verifizierung innerhalb des Bindeschritts 435 der 4A für die Beispielsklasse BAR der 2 zeigt.

5B ein Ablaufdiagramm ist, das eine Verfahrensverifizierung während eines Ausführungsbeispiels des Schritts 530 aus der 5A für die Beispielklasse BAR aus 2 zeigt.

5C ein Ablaufdiagramm ist, das eine Anweisungsverifizierung innerhalb des Verifizierungsanweisungsschritts 537 der 5B zeigt.

6A ein Ablaufdiagramm ist, das eine Verfahrensverifizierung während eines Ausführungsbeispiels der vorliegenden Erfindung für einen Schritt 530 aus 5A für die Beispielklasse BAR aus 2 zeigt, welcher ein vollständig träges Laden zulässt.

6B ein Ablaufdiagramm ist, das eine Anweisungsverifizierung innerhalb des Verifizierungsanweisungsschritts 637 der 6A gemäß einem Ausführungsbeispiel der vorliegenden Erfindung zeigt.

6C ein Ablaufdiagramm ist, das ein Prüfen einer Verifizierungsbeschränkung gemäß einem Ausführungsbeispiel der vorliegenden Erfindung während eines Schritts 475 der 4A für die Beispielklasse BAR der 2 zeigt.

7A ein Ablaufdiagramm ist, das eine Vorverifizierung für eine Klasse-zu-einer-Zeit für die Beispielklasse BAR aus 2 gemäß der vorliegenden Erfindung zeigt.

7B ein Ablaufdiagramm ist, das eine Vorverifizierung eines Verfahrens während eines Schritts 716 der 7A zeigt.

7C ein Ablaufdiagramm ist, das eine Verwendung einer Vorverifizierung für eine Klasse-für-Klasse während eines Schritts 530 in 5A während einer Verifizierung zu einer Laufzeit der Beispielklasse BAR aus 2 gemäß einem Ausführungsbeispiel der vorliegenden Erfindung zeigt.

8 ein Ablaufdiagramm ist, das eine Verwendung einer Klasse-für-Klasse-Vorverifizierung während eines weiteren Ausführungsbeispiels der vorliegenden Erfindung für einen Schritt 530 aus 5A zeigt, welcher ein vollständig träges Laden mit einer Klasse-für-Klasse-Vorverifizierung der Beispielklasse BAR aus 2 zulässt.

9 ein Blockdiagramm eines Computers ist, der für eine Vorverifizierung mit einem Cache für vertrauenswürdige Klassen und Verifizierungsbeschränkungen gemäß einem weiteren Ausführungsbeispiel der vorliegenden Erfindung konfiguriert ist.

Anmerkungen und Nomenklatur

Die detaillierten Beschreibungen, die folgen, können in Bezug auf Programmprozeduren gezeigt werden, die auf einem Computer oder einem Netzwerk von Computern ausgeführt werden. Diese Prozedurbeschreibungen und Darstellungen sind die Mittel, die von Fachleuten auf dem Gebiet verwendet werden, um die Substanz ihrer Arbeit anderen Fachleuten auf dem Gebiet am effektivsten mitzuteilen.

Eine Prozedur stellt man sich hier und allgemein derart vor, dass sie eine eigenkonsistente Sequenz von Schritten ist, die zu einem erwünschten Ergebnis führen. Diese Schritte sind diejenigen, die physikalische Manipulationen von physikalischen Größen erfordern. Normalerweise, wenn auch nicht notwendigerweise, nehmen diese Größen die Form von elektrischen oder magnetischen Signalen an, die gespeichert, transferiert, kombiniert, verglichen und auf andere Weise manipuliert werden können. Es erweist sich, hauptsächlich aus Gründen einer allgemeinen Anwendung, immer als angenehm, auf diese Signale als Bits, Werte, Elemente, Symbole, Zeichen, Ausdrücke, Zahlen oder ähnliches Bezug zu nehmen. Es sollte jedoch beachtet werden, dass alle von diesen und ähnlichen Ausdrücken mit den geeigneten physikalischen Größen zu binden sind und lediglich angenehme Label bzw. Etiketten sind, die auf diese Größen angewendet werden.

Weiterhin wird auf die durchgeführten Manipulationen oft in Ausdrücken, wie beispielsweise Addieren oder Vergleichen, Bezug genommen, die allgemein mit geistigen Operationen verbunden sind, die durch einen menschlichen Bediener durchgeführt werden. Keine solche Fähigkeit eines menschlichen Bedieners ist bei irgendeiner der hierin beschriebenen Operationen, die einen Teil der vorliegenden Erfindung bilden, nötig, oder in den meisten Fällen wünschenswert; die Operationen sind Maschinenoperationen. Nützliche Maschinen zum Durchführen der Operationen der vorliegenden Erfindung enthalten digitale Computer oder ähnliche Vorrichtungen für allgemeine Zwecke.

Die vorliegende Erfindung bezieht sich auch auf eine Vorrichtung zum Durchführen dieser Operationen. Diese Vorrichtung kann für den erforderten Zweck speziell aufgebaut sein, oder sie kann einen allgemeinen Computer aufweisen, wie er durch ein in dem Computer gespeichertes Computerprogramm selektiv aktiviert oder rekonfiguriert wird. Die hierin gezeigten Prozeduren sind nicht in sich selbst bezogen auf einen bestimmten Computer oder eine andere Vorrichtung. Verschiedene allgemeine Maschinen können mit Programmen verwendet werden, die gemäß den Lehren hierin geschrieben sind, oder sie können sich als angenehm erweisen, um eine spezialisiertere Vorrichtung zu bilden, um die erforderlichen Verfahrensschritte durchzuführen. Die erforderliche Struktur für eine Vielfalt von diesen Maschinen wird aus der angegebenen Beschreibung erscheinen.

Beschreibung des bevorzugten Ausführungsbeispiels

1A stellt einen Computer von einem Typ, der zum Ausführen der Erfindung geeignet ist. Von außen gesehen hat ein Computersystem in 1A eine Zentralverarbeitungseinheit 100 mit Diskettenlaufwerken 110A und 110B. Die Bezugszeichen für die Diskettenlaufwerke 110A und 110B sind lediglich symbolisch für eine Anzahl von Diskettenlaufwerken, die durch das Computersystem untergebracht sein könnten. Typischerweise würden diese ein Diskettenlaufwerk, wie beispielsweise 110A, ein Festplattenlaufwerk (nicht extern gezeigt) und ein durch einen Schlitz 110B angezeigtes CD-ROM- oder DVD-Laufwerk enthalten. Die Anzahl und der Typ von Laufwerken sind typischerweise bei unterschiedlichen Computerkonfigurationen unterschiedlich. Der Computer hat eine Anzeige 120, auf welcher Information angezeigt wird. Eine Tastatur 130 und eine Maus 140 sind typischerweise auch als Eingabevorrichtungen verfügbar. Der in 1A dargestellte Computer kann eine SPARC-Workstation von Sun Microsystems, Inc. sein.

1B stellt ein Blockdiagramm der internen Hardware des Computers der 1A dar. Ein Bus 150 dient als die Hauptinformations-Multiplexleitung, die die anderen Komponenten des Computers miteinander bindet. Eine CPU 155 ist die Zentralverarbeitungseinheit des Systems, welche Berechnungen und logische Operationen durchführt, die zum Ausführen von Programmen erforderlich sind. Ein Nurlesespeicher (160) und ein Direktzugriffsspeicher (165) bilden den Hauptspeicher des Computers. Eine Plattensteuerung 170 bildet eine Schnittstelle von einem oder mehreren Diskettenlaufwerken mit dem Systembus 150. Diese Diskettenlaufwerke können Floppydisk-Laufwerke, wie beispielsweise 173, interne oder externe Festplattenlaufwerke, wie beispielsweise 172, oder CD-ROM- oder DVD-(digitale Videoplatten-)Laufwerke, wie beispielsweise 171, sein. Eine Anzeigeschnittstelle 125 bildet eine Schnittstelle für eine Anzeige 120 und lässt zu, dass Information von dem Bus auf eine Anzeige angeschaut wird. Kommunikationen mit externen Vorrichtungen können über ein Kommunikationsport 175 erfolgen.

1C stellt ein beispielhaftes Speichermedium dar, das mit Laufwerken, wie beispielsweise 173 in 1B oder 110A in 1A, verwendet werden kann. Typischerweise werden Speichermedien, wie beispielsweise eine Diskette oder eine CD-ROM, oder eine digitale Videoplatte, die Programminformation zum Steuern des Computers enthalten, um zu ermöglichen, dass der Computer seine Funktionen gemäß der Erfindung durchführt.

1D ist ein Blockdiagramm einer Netzwerkarchitektur, die zum Tragen von Daten und Programmen gemäß einigen Aspekten der Erfindung geeignet ist. Ein Netzwerk 190 dient zum Verbinden eines Client-Computers 100 mit einem oder mehreren Servern, wie beispielsweise einem Server 195 für das Herunterladen von Programm- und Dateninformation. Ein Client 100' kann auch über einen Netzwerk-Serviceprovider mit dem Netzwerk 190 verbunden sein, wie beispielsweise über ISP 180. Die Elemente, die auf eine virtuelle Maschine (VM) oder eine andere Computerarchitektur bezogen sind, die in entweder Hardware oder Software implementiert ist, können über ein Netzwerk verteilt sein, wie es nachfolgend beschrieben ist.

1E zeigt einen einzelnen Computer, der konfiguriert ist, um Komponenten zu haben, die auf eine virtuelle Maschine bezogen sind. Die Komponenten enthalten Quellcodeangaben 162 in einem oder mehreren logischen Blöcken eines Speichermediums im Computer, einen Compiler 164, der den Quellcode 162 kompiliert, um eines oder mehrere Module 165, 166 zu erzeugen, die Anweisungen enthalten, wie beispielsweise VM-Anweisungen, und einen Prozessor, wie beispielsweise eine virtuelle Maschine (VM) 167, die eines oder mehrere Module 165, 166 als Eingabe nimmt und das Programm ausführt, das sie erzeugen. Obwohl es in 1E an einem Computer gezeigt ist, sollte es verstanden werden, dass ein Modul 165 und der Prozessor, z.B. die VM 167, wenigstens temporär auf demselben Computer sitzen müssen. Das Modul kann von einem anderen Computer gesendet werden, der einen Compiler betreibt bzw. laufen lässt, um das Modul aus einem Quellcode zu erzeugen. Beispielsweise zeigt 1D einen Compiler 194 und einen Quellcode 192 am Server 195 und zwei unterschiedliche Implementierungen der virtuellen Maschine 150, 151, und zwar jeweils eine an jedem der zwei Clients 100, 100'. Der Quellcode 192 (und 162 in 1E) kann irgendeine Sprache sein, ist aber vorzugsweise in der Programmiersprache JAVATM-Sprache, und kann durch einen menschlichen Programmierer oder eine Ausgabe von einem anderen Programm geschrieben sein. Das Modul 196, das durch den Compiler 194 an dem Server 195 erzeugt ist, kann über das Netzwerk 190 transportiert und als Modul, wie z.B. 156, an einem der Client-Computer, wie z.B. 100, gespeichert werden. Dort kann die plattformspezifische Implementierung VM, z.B. 150, die Anweisungen im Modul 156 ausführen.

Spezifisch ist die vorliegende Erfindung unter Verwendung der JVM beschrieben, ist aber nicht auf die JVM beschränkt. Die Erfindung gilt für irgendeinen Prozess, der zu einer Laufzeit Programmmodule von verschiedenen Quellen bindet und der diese Programmmodule verifiziert, bevor sie ausgeführt werden.

Als Beispiel für einen Pseudo-Quellcode für ein Programmmodul, das eine Klasse darstellt, die die Zustände zeigt, die Probleme verursachen, die durch die vorliegende Erfindung zu lösen sind, zeigt 2 einen Pseudo-Quellcode, der in einer Programmiersprache gleich der Programmiersprache JAVATM geschrieben ist. Die erste Zeile benennt die Klasse "BAR". Die erste Gruppe von Ellipsen stellt andere Angaben dar, die zu der Definition der Klasse BAR beitragen, aber hier nicht berücksichtigt werden. Die nächste Zeile bis zum Ende des Beispiels definiert ein Verfahren mit dem Namen FOO in der Klasse BAR (was auch als BAR.FOO bezeichnet ist); der Typ "leer" bzw. "void" zeigt an, dass kein Wert zurückgebracht wird, wenn ein Aufruf des Verfahrens FOO endet. Die nächste Zeile führt ein "if else"- bzw. "wenn sonst"-Konstrukt ein, das während einer Ausführung zwei Zweige zur Verfügung stellt. Wenn das Verfahrensargument mit dem Namen "arg" wahr ist, wird ein Zweig ausgeführt, der durch die nächste Gruppe von Ellipsen dargestellt ist, nämlich die Zuordnungsangabe innerhalb der Klammern und der folgenden Ellipsen. Die Zuordnungsangabe gibt an, dass die Variable mit dem Namen "var" vom Klassentyp A einem neuen Fall der Klasse B zugeordnet werden wird. Somit wird in diesem Zweig Bezug auf zwei andere Klassen, die Klasse A und die Klasse B, Bezug genommen, nämlich die Klassen, auf die Bezug genommen wird. Die nächste Zeile, nämlich das else bzw. sonst von dem if-else- bzw. wenn-sonst-Konstrukt signalisiert den Beginn eines anderen Zweigs des Verfahrens, nämlich des Zweigs, der genommen wird, wenn arg falsch ist. Dieser andere Zweig ist zwischen den nächsten Klammern enthalten und wird durch eine andere Gruppe von Ellipsen dargestellt, um anzuzeigen, dass kein Bezug auf entweder die Klasse A oder die Klasse B in diesem Zweig genommen wird. Die Zweige konvergieren wieder bei der Angabe, wo der Wert einer Variablen z seinem ursprünglichen Wert im Quadrat zugeordnet wird.

Unter Verwendung der Beispielsklasse BAR und ihres Verfahrens FOO können der Unterschied zwischen einem eifrigeren Laden, einem nahezu trägen Laden und einem vollständig trägen Laden und die Vorteile der vorliegenden Erfindung in einer virtuellen Maschine, wie beispielsweise der JVM, dargestellt werden. Natürlich arbeitet die JVM nicht an der JAVATM-artigen Programmiersprache, die in 2 aufgelistet ist, sondern arbeitet statt dessen an einem Modul, das Anweisungen enthält, die typischerweise durch einen Compiler erzeugt werden; der Compiler arbeitete bei dem höheren Programmiersprachencode, wie beispielsweise demjenigen, der in 2 aufgelistet ist.

3 zeigt ein vollständig eifrigeres Laden der Beispielsklasse BAR durch eine JVM. Unter der Annahme, dass die Klasse BAR nicht bereits geladen ist, wenn die Zeit kommt, ein Verfahren FOO aufzurufen, das in der Klasse BAR definiert ist, lädt die JVM in einem Schritt 310 die Klasse BAR aus irgendeiner Speichervorrichtung in einen Speicher unter Verwendung des Klassenladers für BAR, wie z.B. des Laders bzw. der Ladeeinheit L1. Die Klasse BAR ist dann die aktuelle Klasse. Da die aktuelle Klasse BAR auf die Klassen A und B Bezug nimmt, ruft die eifrigere JVM die Ladeeinheiten für beide von diesen Klassen ebenso auf, wenn sie nicht bereits geladen sind, und zwar in einem Schritt 320. In 3 sind die Klassenladeeinheiten bzw. Klassenlader für die Klassen A und B jeweils als L2 und L3 bezeichnet; aber L1, L2 und L3 können alle derselbe eingebaute oder anwenderdefinierte Klassenlader sein, oder irgendwelche zwei können dieselben sein, oder jeder kann unterschiedlich sein.

Während eines Bindens 335 wird eine Verifizierung durch die JVM durchgeführt. Viele Details über die Prozeduren, die während einer Verifizierung verwendet werden, sind in dem US-Patent 5,740,441 beschrieben, auf das oben Bezug genommen ist. Wie es in diesem Patent beschrieben ist, enthält eine Verifizierung ein Identifizieren von irgendeiner Anweisungssequenz in einem Verfahren, das versucht, Daten vom falschen Typ zu verarbeiten, oder von irgendwelchen Anweisungen, die einen Unterlauf oder einen Überlauf eines Operandenstapels der virtuellen Maschine verursachen würden. Anweisungen in der JVM sind typenspezifisch, so dass die Operanden, an welchen durch die Anweisung gearbeitet wird, mit dem Typ übereinstimmen müssen, für welchen die Anweisung definiert ist. Ein Operandenstapelüberlauf ist ein Versuch, ein Element, wie beispielsweise einen primitiven Wert oder eine Objektreferenz, auf einen Operandenstapel zu legen, das veranlassen würde, dass der Stapel die voreingestellte maximale Größe für den Stapel überschreitet, die in der Klassendatei definiert ist, d.h. dann, wenn der Stapel bereits voll ist. Ein Operandenstapelunterlauf tritt dann auf, wenn eine Anweisung versucht, ein Element von einem Operandenstapel zu nehmen, wenn keine gültigen Elemente auf dem Stapel gelassen sind, d.h. wenn der Stapel bereits leer ist. Es wird vorausgesetzt, dass irgendwelche Gültigkeitsprüfungen, die vor einer Ausführung der Anweisungen in einem Modul durchgeführt werden können, bei einer Verifizierung enthalten sein können.

Wenn eine Verifizierung eines Moduls fehlschlägt, sollte die virtuelle Maschine den Fehler identifizieren und nicht versuchen, die Anweisungen im Modul auszuführen. Im Fall der JVM verwirft die JVM eine Binde- oder Verifizierungsfehlernachricht (nicht gezeigt), die durch Klassenausnahme-Handhabungseinheiten elegant gehandhabt werden können.

Wenn eine Verifizierung eines Moduls erfolgreich ist und ein Binden beendet ist, kann eine Ausführung beginnen. Bei diesem Beispielsfall kann die aktuelle Klasse BAR initialisiert werden, Schritt 340, und wird das Verfahren FOO.BAR der aktuellen Klasse in Betrieb genommen bzw. laufen gelassen, Schritt 350, da die JVM jede Anweisung interpretiert und sie ausführt. Der Interpreter muss keine Typen prüfen, oder einen Operandenstapelüberlauf oder -unterlauf, weil dies bereits durch eine Verifizierung durchgeführt wurde, die während eines Bindens 335 durchgeführt ist.

Zwei Vorteile des Prozesses, der ein dynamisches Binden enthält, welcher oben beschrieben ist, bestehen darin, dass durch andere entwickelte und kompilierte Klassen sicher verwendet werden können, und das nach einem Verwenden einer Ausführung schneller ist. Durch andere kompilierte Klassen können verwendet werden, weil sie während eines Bindens verifiziert werden, und zwar vor einer Ausführung, um eine Ungültigkeit zu verhindern, und möglicherweise gefährliche Operationen. Weil eine Typenprüfung und ein Operandenstapelüberlauf und -unterlauf während einer Verifizierung durchgeführt wurden, werden sie nicht bei einer Anweisungsausführung durchgeführt, so dass Ausführungszeiten schneller sind. Gleichermaßen können andere Gültigkeitsprüfungen, die während einer Verifizierung durchgeführt werden, bei einer Ausführung sicher übersprungen werden.

Bei einem trägen Laden, wie es in 4A dargestellt ist, wird eine Klasse nicht geladen, bis sie während einer Ausführung nötig ist. Der Vorteil davon kann mit der Probenklasse BAR in 2 dargestellt werden. Wenn arg falsch ist, wird die Zuordnung, die im "if"-Zweig auf die Klassen A und B Bezug nimmt, niemals durchgeführt, und es kann sein, dass weder A noch B geladen oder gebunden werden muss. Somit ist eine Verarbeitung zu einer Laufzeit mit einem trägen Laden schneller.

Beispielsweise werden, wie es in 4A gezeigt ist, nach einem Laden der Klasse BAR mit der Klassenladeeinheit L1 in einem Schritt 410 die Klassen A und B, auf die durch BAR Bezug genommen wird, nicht sofort geladen. Statt dessen wird die Klasse BAR während eines Bindens in einem Schritt 435 verifiziert; und dann, wenn die Klasse BAR eine Verifizierung und ein Binden durchläuft, geht die JVM dazu über, die Klasse BAR in einem Schritt 440 zu initialisieren. Andererseits wird dann, wenn die Klasse BAR ein Binden und eine Verifizierung nicht durchläuft, eine Fehlernachricht ausgeworfen (nicht gezeigt) und wird eine Ausführung nicht versucht (nicht gezeigt). Nachdem die Klasse BAR in Schritt 440 initialisiert ist, wird das Hauptverfahren in der Klasse BAR ausgeführt und wird möglicherweise das Verfahren FOO im Schritt 450 aufgerufen. Wenn die Variable arg falsch ist, wird im Verfahren FOO der "else"-Zweig genommen und weder die Klasse A noch die Klasse B wird verwendet. Dies ist in 4A durch den Entscheidungsschritt 460 dargestellt, der bestimmt, ob die aktuelle Anweisung ein Auflösen einer Referenz zu der Klasse B erfordert. Wenn die Klasse B nicht erforderlich ist, wird die aktuelle Anweisung ausgeführt und fährt die Ausführung mit der nächsten Anweisung fort, die in einer Schleife zurück zu 460 geht, bis keine weiteren Anweisungen zu verifizieren bleiben. Wenn andererseits die Variable arg wahr ist, wird der "if"-Zweig ausgeführt. Dieser Zweig enthält die Zuordnung, bei welcher die Variable var der Typenklasse A auf einen neuen Fall der Klasse B gesetzt wird. Wenn die erste Anweisung, die auf B Bezug nimmt, angetroffen wird, muss ein Verfahren der Klasse B aufgerufen werden (die Bildungseinheit bzw. der Konstrukteur von B) und die Bezugnahme auf die Klasse B muss aufgelöst werden. Der durch den Schritt 460 dargestellte Test, der fragt, ob B für diese Anweisung aufgelöst werden muss, wird bestätigend beantwortet. Dann lädt ein Schritt 470 die Klasse B, wenn sie nicht bereits geladen ist, unter Verwendung des Klassenladers bzw. der Klassenladeeinheit L3.

Bei der herkömmlichen JVM fährt eine Verarbeitung einfach fort, wo ein Nachladeschritt 475 in 4A gezeigt ist, und bewegt sich direkt zu einem Schritt 480. Da ein neuer Fall der Klasse B erzeugt wird, muss sie zuerst gebunden und initialisiert werden. Somit besteht der nächste Schritt für die Klasse B darin, im Schritt 480 gebunden zu werden, wenn sie nicht bereits gebunden worden ist. Wenn die Klasse B ein Binden (einschließlich einer Verifizierung) in einem Schritt 480 durchläuft, dann wird in einem Schritt 490 die Klasse B initialisiert, und dann fährt eine Verarbeitung in einem Schritt 498 fort, in welchem die neu aufgelöste Klasse B durch die aktuelle Anweisung verwendet werden kann.

Dieser Ablauf scheint diesbezüglich vollständig träge zu sein, dass eine Klasse nicht geladen wird, bis sie benötigt wird, um eine Referenz während einer Ausführung aufzulösen. Wie es später gezeigt werden wird, könnte jedoch gemäß der herkömmlichen JVM-Spezifikation der Verifizierungsschritt während eines Bindens 435 das Laden der Klasse B erfordern. In einem solchen Fall kann der Prozess nicht als vollständig träge angesehen werden; und der Prozess wird nahezu träges Laden genannt.

Ein während eines in 4A dargestellten nahezu trägen Ladens identifiziertes Problem ist eine Mehrdeutigkeit eines Klassennamens. Wenn mehrere Klassen miteinander kompiliert werden, erzeugt der Compiler einen Namensraum, der Klassennamen enthält, die innerhalb des Namensraums eindeutig sind. Jedoch dann, wenn mehrere Klassen zu unterschiedlichen Zeiten durch unterschiedliche Compiler kompiliert werden, kann eine Eindeutigkeit der Namen für eine Klasse nicht garantiert werden. Zu einer Laufzeit können Klassenladeeinheiten mehrere Namensräume einführen. Als Ergebnis ist ein Klassentyp während einer Laufzeit nicht durch seinen Namen allein definiert, sondern vielmehr durch die Kombination des Klassennamens und seines definierenden Klassenladers, z.B. <BAR,L1>. Dieser Umstand kann den Verifizierer selbst in dem herkömmlichen System täuschen, wo der Verifizierungsschritt alle Klassen, auf die Bezug genommen wird, lädt, die zum Auflösen von Typen benötigt sind. Während eines Bindens 435 einschließlich einer Verifizierung ist angenommen, dass die Klasse, auf die Bezug genommen ist, wie z.B. B, den Typ hat, der durch den aktuellen Klassenlader, z.B. L1, übertragen werden würde; d.h., dass der "Typ" der Klasse B als <B,L1> angenommen wird. Wenn diese Annahme nicht wahr ist, dann können Probleme von Zugriffsprivilegien entstehen. Beispielsweise dann, wenn der Klassenlader L3 von B unterschiedlich von dem Klassenlader L1 von BAR ist, und dann, wenn <B,L3> eine Variable derart deklariert, dass sie privat ist, und <B,L1> derart deklariert, dass sie öffentlich ist, VM einen Zugriff auf die private Variable von außerhalb der Klasse B zulassen, und eine Programmsicherheit kann kompromittiert werden.

In der allerletzten Version der JVM-Spezifikation, der zweiten Ausgabe, herausgegeben im April 1999, wird dieses Problem vermieden, wie es in einer anderen zugehörigen Anmeldung, nämlich U.S.S.N. 09/134,477 von Bracha und Liang, mit dem Titel METHODS AND APPARATUS FOR TYPE SAFE LAZY, USER-DEFINED CLASS LOADING beschrieben ist, auf welche auch oben Bezug genommen ist. 4B zeigt ein Ablaufdiagramm, das die Lösung darstellt, die in der zweiten Ausgabe der JVM-Spezifikation verwendet wird. Unter Verwendung dieser Lösung sind Zusatzschritte in dem Nachladeschritte 475 enthalten. Der Schritt 473 bestimmt, ob die Klasse B, wie sie tatsächlich mit L3 geladen ist, den angenommenen Typ erzeugt, basierend auf dem Namen und dem Lader L1 von BAR; d.h. der Schritt 473 bestimmt, ob <B,L3> gleich <B,L1 > ist. Wenn ein Laden von B tatsächlich einen Typ erzeugt, der unterschiedlich von dem angenommenen Typ ist, dann verfehlt die Klasse B die Namen/Typ-Beschränkung, und ein Fehler wird im Schritt 474 ausgeworfen. Sonst fährt eine Ausführung im Schritt 479 fort. Dieser Prozess, der in der direkt oben zitierten Anmeldung beschrieben ist, ändert die Tatsache nicht, dass das Binden im Schritt 435 ein Laden der Klassen A und/oder B, auf die Bezug genommen wird, erfordern könnte, um eine Untertypisierung für ihre Verwendung durch die Klasse BAR zu prüfen, wie es nachfolgend beschrieben ist. Somit löst die zitierte Patentanmeldung nicht die Probleme, die mit einem Bereitstellen eines vollständig trägen Ladens interferieren.

Verifizierungsschritte innerhalb eines Bindens 435 der 4A sind für das Beispiel unter Verwendung der 5A, 5B und 5C dargestellt. Die 5A ist ein Ablaufdiagramm, das zeigt, dass ein Binden der Klasse BAR im Schritt 435 ein Starten einer Verifizierung der aktuellen Klasse BAR 510 enthält, möglicherweise gefolgt durch einen Schritt 530, in welchem das Verfahren FOO der aktuellen Klasse BAR sich einer Verifizierung unterzieht. Darauf folgend wird die Verifizierung der Klasse BAR innerhalb des Schritts 435 im Schritt 590 beendet. Die während des herkömmlichen Ausführungsbeispiels 530a des Schritts 530 zum Verifizieren des Verfahrens FOO der Klasse BAR verwendeten Prozeduren sind in 5B gezeigt. Das Verfahren startet im Schritt 532. Wenn das Verfahren auf andere Klassen Bezug nimmt, wie beispielsweise A und B, welche noch nicht bereits geladen sind, kann es für den Verifizierungsprozess nötig sein, die Klassen A und/oder B zu laden. Die erste Bestimmung wird für jede Anweisung im Schritt 555 durchgeführt. Wenn die Klasse B, auf die Bezug genommen wird, nötig ist, wird es dann bestimmt, ob die Klasse B bereits geladen ist, Schritt 540. Wenn sie nötig ist und nicht bereits geladen ist, wird die Referenzklasse geladen (Schritt 550). Somit kann selbst wenn ein träges Laden erwünscht ist, eine Verifizierung von Verfahren andere Klassen laden, bevor die Klassen tatsächlich während einer Ausführung nötig sind. Wie es durch einen Schritt 537 dargestellt ist, wird dann, wen eine nicht richtige Untertypisierungsbeziehung zwischen A und B oder ein anderes Verifizierungsproblem während einer Verifizierung gefunden wird, ein Verifizierungsfehler im Schritt 539 ausgeworfen. Wenn die aktuelle Anweisung eine Verifizierung durchläuft, fährt der Verifizierungsprozess bis zu dem Ende des Verfahrens im Schritt 582 unter einem Gehen in einer Schleife zurück zum Schritt 555 fort, bis keine weiteren Anweisungen verifiziert werden müssen. Das bedeutet, dass eine ausreichende Gruppe von Anweisungen verifiziert wird, so dass eine Ausführung des Verfahrens beginnen kann.

5C zeigt einige beispielhafte Details einer Verifizierung, die während des Schritts 537 durchgeführt werden kann; beispielsweise wie es in der JVM durchgeführt wird und wie es im US-Patent 5,740,441 beschrieben ist, 4B. Bei diesem Beispiel wird eine Typenmomentaufnahme für jede Anweisung beibehalten. Die Typenmomentaufnahme ist eine Struktur, die die Typen für eine Liste von lokalen Variablen und für jede Position auf einem Operandenstapel hält. Wenn eine Anweisung verifiziert werden muss, wird ihre Momentaufnahme geladen, Schritt 533. In einem Schritt 534 wird die Auswirkung der Ausführung der Anweisung auf die Typen in der Momentaufnahme bestimmt. Wenn eine Anweisung ein Nachfolger von mehreren anderen Anweisungen ist, wie beispielsweise dann, wenn zwei Zweige von Operationen konvergieren (wie bei der Angabe, die "z" bei dem Beispielsverfahren BAR.FOO in 2 enthält), muss die Typenmomentaufnahme für eine Anweisung mit den Momentaufnahmen der Vorläuferanweisungen auf jedem der Zweige verknüpft werden. Dies wird erreicht, während eine Anweisung durch Bestimmen der Nachfolgeranweisungen zu der aktuellen Anweisung in einem Schritt 535 verifiziert wird und während die Momentaufnahme der aktuellen Anweisung mit derjenigen von jedem Nachfolger in einem Schritt 536 verknüpft wird. Dieses Verknüpfen wird einen Verifizierungsfehler erfassen, wenn primitive Typen bei denselben Stellen in der Momentaufnahme nicht übereinstimmen. Die Verknüpfung ersetzt auch Referenzen bei derselben Position in den Verknüpfungsmomentaufnahmen mit dem spezifischsten allgemeinen Supertyp (was auch die unterste obere Grenze LUB oder der am wenigsten allgemeine Supertyp LCS genannt wird) in der resultierenden verknüpften Momentaufnahme; und eine Verifizierung schlägt dann fehl, wenn dies nicht durchgeführt werden kann.

Wie es durch 5B gezeigt ist, kann eine Verifizierung eines Verfahrens, das auf andere Klassen Bezug nimmt, ein vollständig träges Laden verhindern, weil es sein kann, dass der Verifizierer Klassen laden muss, auf die Bezug genommen wird. Das Laden von Klassen, auf die Bezug genommen wird, ist nicht gesichert – es hängt von dem Kontext ab, in welchem die Referenzen gemacht werden. Bei dem Beispiel muss A eine Superklasse von B für die Zuordnungsangabe sein, um legal zu sein. Diese Untertypbeziehung kann durch Laden der Klasse B geprüft werden. Wenn A eine Superklasse von B ist, würde A selbst in dem Prozess eines Ladens von B geladen worden sein. Wenn A nach einem Laden von B nicht geladen wird, kann sie nicht eine Superklasse B sein. Wenn A geladen wird, kann man direkt prüfen, ob die Beziehung gilt.

Verifizierung mit vollständig trägem Laden

Um ein vollständig träges Laden mit einer Verifizierung gemäß der vorliegenden Erfindung zu erreichen, muss es möglich gemacht werden, das Prüfen von Quermodulbeziehungen zu verzögern, die ein Laden gemäß einer herkömmlichen Praxis triggern bzw. anstoßen bzw. veranlassen.

Wenn B während der Verifizierung der Beispielsklasse BAR bereits geladen ist, kann man sofort bestimmen, ob die Untertypisierungsbeziehung gilt. Der Supertyp ist entweder beim Laden von B geladen worden, oder er kann sonst kein Supertyp von B sein. Wenn die Klasse B nicht bereits geladen ist, wird gemäß der vorliegenden Erfindung eine Beschränkung an der Klasse B platziert oder dieser auferlegt, welche geprüft oder geltend gemacht werden wird, nachdem die Klasse B geladen ist, wenn sie es jemals wird. Ein Beispiel für dieses Ausführungsbeispiel der Erfindung ist in 6A bis 6C dargestellt.

6A ist ein Ablaufdiagramm für eine Implementierung 530b für den in 5A gezeigten Verfahrensverifizierungsschritt 530 und ist eine Alternative zu der in 5B gezeigten Version 530a für die herkömmliche JVM Spezifikation. Gemäß diesem Ausführungsbeispiel der vorliegenden Erfindung startet die Verfahrensverifizierung in einem Schritt 632 und bestimmt, ob Information über die Klasse B, auf die Bezug genommen wird, von dem Typ, der herkömmlich ein Laden triggert, nötig ist, Schritt 655. Wenn die Klasse B, auf die Bezug genommen wird, ein Laden auf herkömmliche Weise triggern würde, prüft die Prozedur als nächstes, ob die Klasse B, auf die Bezug genommen wird, bereits geladen ist, Schritt 640. Wenn die Klasse B bereits geladen ist, dann kann eine Verarbeitung wie in der herkömmlichen JVM mit einem Prüfen der Untertypisierung und anderen Gültigkeitsprüfungen in einem Schritt 637 und einem Auswerfen des Fehlers in einem Schritt 639, wenn eine Anweisung bei einer Verifizierung fehlschlägt, fortfahren. Wenn die Anweisung die Gültigkeitsprüfungen einschließlich von Zwischenmodulprüfungen nicht erfüllt, dann fährt eine Verifizierung des Verfahrens FOO unter einem Laufen in einer Schleife durch ausreichende Anweisungen fort, bis keine weiteren Anweisungen verifiziert werden müssen, um eine Ausführung zu beginnen, Schritt 682. Wenn irgendeine Anweisung, die zum Beginnen einer Ausführung nötig ist, bei einer Verifizierung fehlschlägt, würde eine Ausführung des Moduls nicht beginnen.

Jedoch dann, wenn in einem Schritt 640 bestimmt wird, dass die Klasse B nicht bereits geladen ist, wird zu dieser Zeit die Klassenladeeinheit für die Klasse B nicht aufgerufen, um die Klasse B zu laden. Statt dessen werden Verifizierungsbeschränkungen für die Verwendung der Klasse BAR der Klasse B in einem Schritt 650 geschrieben. Dann wird angenommen, dass alle Kreuz- bzw. Quermodulprüfungen bei B, wie beispielsweise Untertypisierungsprüfungen, durchlaufen sind, und die Verifizierung des Verfahrens FOO fährt in einem Schritt 682 fort, wie zuvor. Die Umstände, die zu einem Schreiben von Beschränkungen führen, und die Form dieser Beschränkungen im Schritt 650 werden für die Beispiele später detaillierter beschrieben. Gemäß diesem Ausführungsbeispiel der vorliegenden Erfindung interferiert der Verifizierungsschritt 530b während eines Bindens nicht das vollständig träge Laden von Modulen, wie es erwünscht ist.

Verifizierung mit symbolischer Berechnung von LUB

Wenn ein Modul oder eine Klasse, auf welches bzw. welche Bezug genommen wird, noch nicht geladen ist, bleibt es bzw. sie während eines solchen vollständig trägen Bindens nicht geladen. In der JVM wirkt sich dies nichtig auf das Ergebnis eines Bindens von Momentaufnahmen aus, weil die im Schritt 538 eingefügte LUB, die in 5C dargestellt ist, nicht bekannt sein kann. Anders ausgedrückt, kann es sein, dass die Darstellung des Typengitters durch die JVM nicht ausreichend bevölkert ist, um die LUB für die mehreren unterschiedlichen Typen, auf die Bezug genommen wird, zu bestimmen. 6B zeigt, wie die Verknüpfungsmomentaufnahmenfunktion gemäß einem Ausführungsbeispiel der vorliegenden Erfindung erreicht wird. Schritte 633, 634, 635 und 636 sind analog zu entsprechenden Schritten 533, 534, 535 und 536. Jedoch kann im Schritt 638, wenn die LUB nicht bekannt ist, ihr Typ nicht in die geeignete Position der verknüpften Momentaufnahme eingefügt werden. Statt dessen wird eine Liste von Typen, auf die Bezug genommen wird, bei der geeigneten festen Position in den Momentaufnahmen der Vorläuferanweisungen eingefügt oder auf andere Weise mit dieser festen Position in der verknüpften Momentaufnahme gebunden. Das bedeutet, dass anstelle eines Identifizierens und eines Platzierens der Referenz zu einer LUB in der Momentaufnahme bei dieser Stelle durch Laden von Klassen oder Modulen, wie es nötig ist, um das Typengitter zu bilden, die mehreren Referenzen zu unterschiedlichen Typen, wie z.B. die Klassentypen X1, X2,..., Xn, die die Notwendigkeit für eine LUB veranlassen, symbolisch aufgelistet werden, und zwar vielleicht separiert durch ein Zeichen oder ein Symbol, wie Brennstoffzellensystem ein ^. Das Symbol zeigt an, dass die Typen diese Beziehung gemeinsam nutzen müssen, dass sie eine LUB haben.

Geltendmachen von Beschränkungen

Die Beschränkungen, die für eine Verwendung durch die VM in einem Schritt 650 geschrieben oder auf andere Weise aufgezeichnet sind, werden geltend gemacht, z.B. wird geprüft, wann und wenn eine Klasse B, auf die Bezug genommen wird, tatsächlich geladen wird. Somit werden die Beschränkungen direkt nach einem Laden während des Nachladeschritts, der durch den Schritt 475 in 4A dargestellt ist, geltend gemacht. 6C stellt das Geltendmachen von Verifizierungsbeschränkungen an der Klasse B, auf die Bezug genommen wird, gemäß einem beispielhaften Ausführungsbeispiel der vorliegenden Erfindung dar. Dieses Ausführungsbeispiel der Erfindung stellt einen neuen Prozess 475b dar, der die Schritte von 475a enthalten kann, was in 4B dargestellt ist. Das Geltendmachen beginnt bei einem Schritt 671. Bei den Beispielen werden die aktuellen Supertypen von B dazu verwendet, zu bestimmen, ob B die zuvor geschriebenen Untertypisierungs-Verifizierungsbeschränkungen erfüllt. Diese Prüfung wird in einem Schritt 673 durchgeführt. Wenn die Klasse B, auf die Bezug genommen wird, die Beschränkungen nicht erfüllt, dann wird in einem Schritt 674 ein Fehler ausgeworfen. Die Handhabungseinheit für diesen Fehler kann dann eine Ausführung beenden oder zulassen, dass eine Ausführung fortfährt. Alternativ dazu kann eine Ausführung ohne ein Auswerfen eines Fehlers beendet werden. Wenn die Klasse B, auf die Bezug genommen wird, die geschriebenen Beschränkungen erfüllt, dann endet die Nachladeverarbeitung im Schritt 679.

Mit solchen Modifikationen kann eine VM ein vollständig träges Laden mit einer Verifizierung implementieren. Die Vorteile eines Auferlegens eines vollständig trägen Ladens enthalten:

  • • Das Verhalten eines Programms in Bezug auf Bindefehler ist dasselbe auf allen Plattenformen und bei allen Implementierungen.
  • • Man muss nicht alle Stellen vorwegnehmen, wo eine Klasse oder ein Verfahren gebunden werden könnte, und versuchen, Ausnahmen bei allen diesen Stellen zu fangen.
  • • Anwender können die Verfügbarkeit von Klassen oder anderen Modulen auf eine zuverlässige und einfache Weise bestimmen.

Einer der Vorteile der vorliegenden Erfindung besteht darin, dass ein Programmierer auf die Verfügbarkeit von Klassen auf einer Plattform auf eine zuverlässige und einfache Weise testen kann. Beispielsweise dann, wenn ein Programmierer wünscht, Module einer neueren Ausgabe zu verwenden und diese neueren Module nur zu verwenden, wenn sie verfügbar sind, macht ein träges Binden dies einfacher. Irgendwo in dem Code, der durch den Programmierer in diesem Fall erzeugt ist, wird ein Zweig mit einer Referenz zu den neuen Modulen der neuen Ausgabe sein. Eine Ausführung von diesem Zweig wurde durch den Programmierer derart entworfen werden, dass sie nicht auftritt, wenn die aktuelle Version der Plattform die Module, auf die in diesem Zweig Bezug genommen wird, nicht unterstützt. Wenn das neue Modul auf dieser Plattform nicht verfügbar ist und das Modul, das verifiziert wird, auf das neue Modul Bezug nimmt, kann eine virtuelle Maschine, die nicht vollständig träge ist, den Verifizierer erfordern bzw. benötigen, um zu versuchen, das fehlende neue Modul zu laden. Dieses Laden wird notwendigerweise fehlschlagen, was zu einem Ausfall bzw. Fehler des Verifizierungsschritts führen wird. Somit wird eine Verifizierung einen Fehler aufgrund eines fehlenden Moduls selbst dann veranlassen, wenn auf das Modul nur in einem Zweig Bezug genommen wird, der niemals ausgeführt werden würde. Wenn ein vollständig träges Laden erforderlich ist, wird eine Verifizierung nicht fehlschlagen, weil Module, auf die durch Anweisungen Bezug genommen wird, nicht tatsächlich ausgeführt werden. Diese Fähigkeit zum Durchlaufen einer Verifizierung, während auf die letzten Ausgaben bzw. Veröffentlichungen von Modulen geprüft wird, wie beispielsweise Klassen, stellt eine signifikante Motivation zum Annehmen eines vollständig trägen Ladens zur Verfügung, welches durch die vorliegende Erfindung unterstützt wird, als ein Erfordernis für eine virtuelle Maschine.

Selbst wenn ein träges Laden erforderlich ist, könnten unterschiedliche Implementierungen einer VM frei sein, früher zu laden und zu binden – vorausgesetzt, dass irgendwelche Fehler bzw. Fehlschläge sich selbst nur bei den legalen definierten Stellen manifestieren. Der Code muss dazu fähig sein, bis zu der Stelle auszuführen, an welcher die Klasse mit dem Fehlertyp aufgelöst werden muss. Beispielsweise kann ein zeitgenauer (JIT = just-in-time) Codegenerator auswählen, eine Klasse oder ein Verfahren im Voraus zu binden, wenn er sie oder es kompiliert. Jedoch dann, wenn irgendein Binden fehlschlägt, eher als dass es sofort fehlschlägt, sollte der JIT einen Code erzeugen, der veranlassen wird, dass die geeignete Ausnahme an der Stelle hervorgerufen wird, bei welcher sonst ein träges Laden dies durchgeführt haben würde (es muss nicht tatsächlich die Binde-Zeittests durchführen, obwohl es dies kann). Als weiteres Beispiel kann ein statischer Compiler während seiner Eigentumsbindephase aufgrund einer ungültigen Klassenreferenz fehlschlagen. Wenn er nichtsdestoweniger auswählt, einen Code zu kompilieren, selbst wenn er nicht vollständig gebunden sein kann, muss dieser Code fehlschlagen, wenn er ausgeführt wird, und zwar an derselben Stelle, wie es ein Code würde, der durch den JIT kompiliert ist. Als letztes Beispiel kann dann, wenn eine Klasse (z.B. durch eine Klassenladeeinheit) dynamisch geladen wird, eine Implementierung auswählen, sie gänzlich oder teilweise im Voraus zu binden. Jedoch dann, wenn es irgendwelche Ausfälle gibt, muss der Code wieder dazu fähig sei, bis zu der Stelle der ungültigen Referenz auszuführen.

Modul-für-Modul-Verifizierung

Gemäß einem weiteren Aspekt der vorliegenden Erfindung wird eine Verifizierung eines Moduls, auf das Bezug genommen wird, selbst dann nicht durchgeführt, wenn ein Modul, auf das Bezug genommen wird, nicht geladen ist. Diese Modul-für-Modul-Verifizierung, die auch Verifizierung für Ein-Modul(Klasse)-zu-einer-Zeit genannt wird, ist aufgrund einer Anzahl von Gründen wünschenswert. Sie lässt zu, dass einer Verifizierung vor einer Laufzeit mit vorteilhaften Konsequenzen durchgeführt wird. Die Laufzeitkosten einer Verifizierung bezüglich der Zeit und des Raums können reduziert oder insgesamt entfernt werden. Eine redundante oder Betrieb-für-Betrieb-Verifizierung kann vermieden werden. Die JAVATM-Laufzeitumgebung kann kleiner und einfacher sein, weil die Menge an Code, der eine Verifizierung implementiert, die sie enthält, reduziert werden kann. Diese Verifizierung für Ein-Modul-zu-einer-Zeit, die als eine Erweiterung für die JAVATM-Plattform als Klasse-für-Klasse-Verifizierung implementiert ist, ist nicht durch eine herkömmliche JVM-Spezifikation automatisch zur Verfügung gestellt, oder durch das oben beschriebene vorgeschlagene vollständig träge Laden. Im ersten Fall lädt der Verifizierer automatisch Klassen, auf die Bezug genommen wird, wenn es nötig ist, ohne eine Option, dies zu vermeiden. Im letzteren Fall wird eine Verifizierung der Klasse, auf die Bezug genommen wird, erfolgen, wenn die Klasse, auf die Bezug genommen wird, geladen ist, und diese Verifizierung wird auch ohne eine Option dafür durchgeführt, dies zu vermeiden. Somit werden zwei Ausführungsbeispiele einer Klasse-für-Klasse-Verifizierung vorausgesehen, und zwar eines, das mit dem herkömmlichen JVM-Entwurf verwendet werden kann, und eines, das mit dem neuen vollständig trägen Ladeentwurf verwendet werden kann.

Gemäß einem Ausführungsbeispiel dieser Erfindung können die normalerweise während einer Verifizierung durchgeführten Prüfungen vor einer Laufzeit durchgeführt werden. Weil Prüfungen vor einer Laufzeit technisch kein Teil eines Bindens sind und somit kein Teil der Verifizierungsstufe eines Bindens, sind diese Prüfungen hierin als Vorverifizierung bezeichnet, was potentiell Vor-Laufzeitprüfungen einer Gültigkeit anzeigt.

Bei diesem Ausführungsbeispiel kann der Programmierer zu irgendeiner Zeit, nachdem eine binäre Klasse durch einen Compiler erzeugt worden ist, eine Vorverifizierung an der binären Klasse durchführen und dies unabhängig von irgendeiner anderen Klasse durchführen, auf die in dieser Klasse Bezug genommen werden könnte. Als Konsequenz ist ein Zugriff auf eine Klasse, auf die Bezug genommen wird, oder auf ein Modul, auf das Bezug genommen wird, nicht erforderlich. Diese Klasse-für-Klasse-Vorverifizierung der vorliegenden Erfindung ist in 7a dargestellt. Das Verfahren beginnt beispielsweise mit einem Laden der Klasse BAR aus einem Speichermedium in einen Speicher, Schritt 710. Dann werden in einem Schritt 712 die Gültigkeitsprüfungen durchgeführt, wie beispielsweise Typenprüfungen und Operandenstapelüberlauf/unterlaufprüfungen, die auf herkömmliche Weise während einer Verifizierung durchgeführt werden würden. Während solcher Prüfungen wird irgendeine Zwischenmodulinformation, die für eine Verifizierung von Anweisungen nötig ist, die auf andere Module Bezug nehmen, wie beispielsweise Untertypisierungsbeziehungen zwischen den Klassen A und B, auf die von der Klasse BAR Bezug genommen wird, optimistisch so angenommen, dass Anweisungen gültig sind. Jedoch erlegt die angenommene Information oder Beziehung dem Modul, auf das Bezug genommen wird, eine Beschränkung auf, an die sich die virtuelle Maschine erinnern muss. Solche Beschränkungen müssen geprüft werden, wenn ein solches Modul, auf das Bezug genommen wird, letztlich geladen wird. Wenn das Modul, wie beispielsweise die Klasse BAR, trotz dieser Annahmen die durchgeführten Prüfungen nicht durchläuft, resultiert dies in einem Fehler, Schritt 713. Da ein solcher Fehler nicht notwendigerweise ein Laufzeitfehler ist, könnte es sein, dass er während einer Ausführung nicht zu einer Handhabungseinheit ausgeworfen wird. Statt dessen könnte ein solcher Fehler zum Programmierer kommuniziert worden sein, wie beispielsweise unter Verwendung einer Fehlernachricht, die auf einer Ausgabevorrichtung, wie beispielsweise einem Drucker oder einem Anzeigebildschirm, erscheint. Wenn das Modul alle Prüfungen durchläuft, dann werden irgendwelche erneut aufzurufende Vorverifizierungsbeschränkungen in einem Schritt 716 für ein spätere Verwendung zur Laufzeit geschrieben. Darauf folgend stoppt der Prozess beim Schritt 719, wenn eine Vorverifizierung beendet ist. Eine weitere Klasse oder ein weiteres Modul kann dann den in 7A dargestellten Schritten folgend vorverifiziert werden. Es kann sein, dass nicht alle Anweisungen in einem Modul vorverifiziert werden müssen, und zwar gerade die Anweisungen, die für eine bestimmte Verwendung des Moduls nötig sind. Beispielsweise kann es nur nötig sein, die Anweisungen im Verfahren FOO zu verifizieren, nicht aber andere Verfahren in der Klasse BAR.

Optional können die Vorverifizierungsbeschränkungen zu einer Datei geschrieben werden oder auf andere Weise mit dem Modul verbunden werden, für ein späteres Prüfen zu einer Laufzeit. Zur Verwendung mit der JVM könnten diese Beschränkungen als zu der Klasse gehörende Daten in dem binären Klassenformat auf dem Speichermedium aufgezeichnet werden. Wenn die Klasse in einen Speicher geladen wird, könnten diese Beschränkungen durch die JVM internalisiert bzw. verinnerlicht werden, um zu prüfen, wann es nötig wird, wie beispielsweise nach einem Laden der Klasse B, auf die Bezug genommen wird.

Als weitere Option können gemäß dieser Erfindung die Vorverifizierungsbeschränkungen, jedoch gespeichert, oder das Modul selbst, oder das Modul selbst, oder beides, ein Signal angebracht haben, wie beispielsweise eine digitale Signatur, das dazu verwendet werden kann, die Quelle des Moduls oder der Beschränkungen zuverlässig zu identifizieren und anzuzeigen, ob sie verfälscht worden sind, seit sie signiert sind.

Auf diese Weise können Innenmodulverifizierungsprüfungen für eine Gültigkeit gleichbedeutend mit denjenigen, die während einer herkömmlichen Verifizierung durchgeführt werden, die aber keine Kreuz- bzw. Quermodulinformation über Module, auf die Bezug genommen wird, erfordern, wie beispielsweise die Klassen A und B, vor einer Laufzeit durchgeführt werden. Das bedeutet, dass eine vollständige Modul-für-Modul-Vorverifizierung für die Innenmodulprüfungen durchgeführt werden kann. Zwischenmodulprüfungen werden in Vorverifizierungsbeschränkungen umgewandelt.

7B stellt Details eines Schritts 716 aus der 7A für den Beispielfall dar. Der Prozess startet eine Vorverifizierung eines Verfahrens einer geladenen Klasse BAR, Schritt 732. Als Nächstes wird bestimmt, ob die nächste Anweisung in dem Verfahren Information von einer Klasse B, auf die Bezug genommen wird, erfordert, damit die Anweisung ihre Gültigkeit geprüft hat (Schritt 755). Wenn es nicht so ist, dann führt die Prozedur irgendwelche erforderlichen Zwischenklassen-Gültigkeitsprüfungen an der Anweisung in einem Schritt 737 durch. Wenn die Anweisung bezüglich der Zwischenklassenprüfung fehlschlägt, wird eine Fehlernachricht zu einer Ausgabevorrichtung geschrieben. Der Programmierer kann dann dieses Problem behandeln. Wenn andererseits eine Klasse, auf die Bezug genommen wird, geladen werden müsste, um ihre Anweisung vollständig zu verifizieren, wird eine Vorverifizierungsbeschränkung für einen späteren Wiederaufruf in einem Schritt 750 geschrieben oder auf andere Weise aufgezeichnet, und die Untertypisierungsbeziehung, die durch die Anweisung erforderlich ist, wird als gültig angenommen. Da Die Anweisung auch Innenklassenprüfungen erfordern kann, geht eine Steuerung zu einem Schritt 737, um diese durchzuführen. Wenn die Anweisung keine Innenklassenprüfungen benötigt, dann "durchläuft" sie automatisch die Prüfungen bei dem Schritt 737. Wenn die Anweisung nach einer Innenklassenprüfung für gültig befunden wird, und/oder nach einem Schreiben einer Vorverifizierungsbeschränkung als gültig angenommen wird, schaltet eine Ablaufsteuerung zu einem Schritt 782, der in einer Schleife zu einem Schritt 755 geht, bis keine weiteren Anweisungen in dem Verfahren FOO der geladenen Klasse BAR bleiben, zu welcher Zeit eine Vorverifizierung des Verfahrens FOO beendet wird. Es ist zu beachten, dass keine Bestimmung diesbezüglich durchgeführt wird, ob eine Klasse, auf die Bezug genommen wird, geladen ist; entweder wird eine Innenmodulprüfung durchgeführt oder eine Vorverifizierungsbeschränkung wird geschrieben. Keine Quermodulprüfung wird selbst mit einem Modul durchgeführt, das bereits geladen ist.

7C zeigt, wie ein Modul, das vor einer Laufzeit bezüglich Ein-Modul-zu-einer-Zeit verifiziert worden ist, durch die während eines Bindens zu einer Laufzeit durchgeführte Verifizierung gehandhabt wird, wie beispielsweise die Klasse BAR. Anstelle von entweder dem Schritt 530a der herkömmlichen JVM oder dem modifizierten Schritt 530b für ein vollständig träges Laden zeigt 7C einen alternativen Schritt 530c, der dem nahezu trägen Laden der herkömmlichen JVM folgt und eine Klasse-für-Klasse-Vorverifizierung enthält. Nach einem Starten des Verifizierungsschritts für Anweisungen eines Moduls, wie beispielsweise das Verfahren FOO der Klasse BAR, in einem Schritt 792 wird eine Bestimmung diesbezüglich durchgeführt, ob das Modul eine Vorverifizierung in einem Schritt 780 durchlaufen hat. Wenn es nicht so ist, folgt die Steuerung dem Ablauf der herkömmlichen JVM beginnend beim Schritt 555 in 5B. Sonst läuft die Steuerung nach einem optionalen Prüfen in einem Schritt 783, ob dem vorverifizierten Modul zu vertrauen ist, was weiter unten beschrieben wird, zu einem Schritt 784. Eine Vielfalt von Wegen ist im Stand der Technik bekannt, um zu testen, ob eine Datei vertrauenswürdig ist, wie beispielsweise durch Verwenden einer digitalen Signatur. Wenn es keine Sorge bezüglich der Vertrauenswürdigkeit von vorverifizierten Modulen gibt, kann der Schritt 783 übersprungen werden. Bei einem Schritt 784 liest der Laufzeitverifizierer, anstelle eines Laufens durch die Anweisungen im Verfahren, die während der Klasse-für-Klasse-Verifizierung von BAR aufgezeichneten/geschriebenen Vorverifizierungsbeschränkungen. Wenn es keine geschriebenen Vorverifizierungsbeschränkungen gab, wird eine Verifizierung von BAR.FOO beendet und geht eine Steuerung zu einem Schritt 778, um den Prozess abzuschließen.

Wenn eine Vorverifizierung für ein Modul, auf das Bezug genommen wird, wie z.B. die Klassen A oder B, geschrieben wurde, dann bestimmt der Laufzeitverifizierer, ob das Modul, auf das Bezug genommen wird, in der Beschränkung bereits geladen ist (Schritt 786). Wenn es so ist, wird die Vorverifizierungsbeschränkung in einem Schritt 788 erzwungen. Wenn das Modul, auf das Bezug genommen wird, bezüglich der Beschränkung fehlschlägt, wird ein Fehler zum Fangen durch eine Fehlerhandhabungseinheit ausgeworfen (Schritt 762). Sonst geht eine Steuerung zu einem Schritt 778, der in einer Schleife durch die Vorverifizierungsbeschränkungen läuft, bis keine übrig bleiben. Wenn im Schritt 786 bestimmt wird, dass das Modul, auf das Bezug genommen wird, wie beispielsweise eine Klasse, auf die Bezug genommen wird, nicht geladen ist, dann wird das Modul, auf das Bezug genommen wird, wie beispielsweise eine Klasse, in einem Schritt 789 geladen und wird die Beschränkung in einem Schritt 788 erzwungen.

Solange die Klasse vorverifiziert worden ist (und optional Vertrauensprüfungen durchläuft), gleichgültig, ob Vorverifizierungsbeschränkungen bezüglich einer Klasse, auf die Bezug genommen wird, geschrieben wurden oder nicht, müssen keine Innenklassenprüfungen durchgeführt werden; sie wurden bereits während der Klasse-für-Klasse-Vorverifizierung vor einer Laufzeit durchgeführt. Gemäß der vorliegenden Erfindung führt dann, nachdem ein Modul eine Vorverifizierung für Ein-Modul-zu-einer-Zeit durchläuft, eine Laufzeitverifizierung keine Innenmodulprüfungen durch; sie erzwingt nur Zwischenmodulbeschränkungen.

Bei dem beschriebenen Beispiel wird ein Modul vorverifiziert, sobald es kompiliert wird, ohne irgendein anderes Modul zu laden. Dies lässt zu, dass vieles einer Verifizierung vor einer Laufzeit durchgeführt wird und nicht jedes Mal wiederholt wird, wenn ein Modul geladen und gebunden wird, um dadurch wertvolle Zeit- und Raumressourcen einzusparen (z.B. auf Prozessoren, die die virtuelle Maschine laufen lassen).

Modul-für-Modul-Vorverifizierung mit vollständig trägem Laden

8 zeigt ein Ablaufdiagramm, das die Ergebnisse einer Vorverifizierung während eines vollständig trägen Ladens zur Laufzeit enthält. 8 zeigt, wie ein Modul, das in Bezug auf Ein-Modul-zu-einer-Zeit vor einer Laufzeit verifiziert worden ist, durch die Verifizierung gehandhabt wird, die während eines Bindens durchgeführt wird, das ein vollständig träges Laden unterstützt, wie beispielsweise die Klasse BAR. Anstelle von entweder dem Schritt 530a der herkömmlichen JVM oder dem modifizierten Schritt 530b für ein vollständig träges Laden oder dem Schritt 530c für ein nahezu träges Laden mit einer Verifizierung für Ein-Modul-zu-einer-Zeit zeigt 8 einen alternativen Schritt 530d, der dem vollständig trägen Laden eines neuen Ausführungsbeispiels der JVM folgt und eine Klasse-für-Klasse-Vorverifizierung enthält. Schritte 892, 880, 883, 884, 878, 886 und 862 in 8 sind analog zu Schritten mit entsprechenden sieben Hunderter-Zahlen in 7C, nämlich jeweils 792, 780, 783, 784, 778, 786 und 762. Nach einem Starten des Verifizierungsschritts für Anweisungen eines Moduls, wie beispielsweise das Verfahren FOO der Klasse BAR, in einem Schritt 892 wird eine Bestimmung diesbezüglich durchgeführt, ob das Modul eine Vorverifizierung durchlaufen hat, und zwar in einem Schritt 880. Wenn es nicht so ist, folgt die Steuerung dem Ablauf des vollständig trägen Ladens der JVM beginnend beim Schritt 655 in 6A. Nach einem optionalen Prüfen in einem Schritt 883, der oben beschrieben ist, ob dem vorverifizierten Modul zu vertrauen ist, läuft die Steuerung zu einem Schritt 884. Bei einem Schritt 884 liest der Laufzeitverifizierer anstelle eines Laufens durch die Anweisungen in dem Verfahren die Vorverifizierungsbeschränkungen, die während der Klasse-für-Klasse-Verifizierung von BAR geschrieben sind. Wenn es keine geschriebenen Vorverifizierungsbeschränkungen gab, wird eine Verifizierung von BAR.FOO beendet und geht eine Steuerung zum Schritt 878 um den Prozess abzuschließen.

Wenn eine Vorverifizierungsbeschränkung für ein Modul, auf das Bezug genommen wird, wie z.B. die Klasse A oder B, gelesen wird, dann bestimmt der Laufzeitverifizierer, ob das Modul, auf das Bezug genommen wird, in der Beschränkung bereits geladen ist, Schritt 886. Wenn es so ist, wird die Vorverifizierungsbeschränkung in einem Schritt 888 erzwungen. Wenn das Modul, auf das Bezug genommen wird, bezüglich der Beschränkung fehlschlägt, wird ein Fehler zum Fangen durch eine Fehlerhandhabungseinheit ausgeworfen, Schritt 862. Wenn das Modul, auf das Bezug genommen wird, die Beschränkung ohne Qualifikation durchläuft, geht ein Ablauf zu einem Schritt 878, der in einer Schleife durch die Vorverifizierungsbeschränkungen läuft, bis keine übrig bleiben.

Die übrigen Schritte in 8 für ein vollständig träges Laden unterscheiden sich wesentlich von ihren Gegenstücken für ein nahezu träges Laden. Wenn im Schritt 886 bestimmt wird, dass das Modul, auf das Bezug genommen wird, wie beispielsweise eine Klasse, auf die Bezug genommen wird, nicht geladen ist, dann wird das Modul, auf das Bezug genommen wird, nicht geladen. Statt dessen wird die Vorverifizierungsbeschränkung zu einem Speicher oder einem Speichermedium kopiert oder auf andere Weise darin gehalten, Schritt 889, um dann, wenn das noch nicht geladene Modul, wie beispielsweise eine Klasse, geladen wird, erzwungen zu werden, wenn jemals.

In 8 kann das Erzwingen des Schritts 888 drei Ergebnisse haben. Neben einem Fehlschlag und einem Durchlaufen ohne Bedingung, ist es möglich, dass das bereits geladene Modul, auf das Bezug genommen wird, nur dann durchlaufen kann, wenn die Inhalte von einem oder mehreren anderen noch nicht geladenen Modulen bekannt sind. Dieses Ergebnis kann als "Übergeben eines Subjekts zu einem Zustand bzw. einer Bedingung" angesehen werden, damit die Vorverifizierungsbeschränkung an mehreren Modulen, auf die Bezug genommen wird, als Vorverifizierungsbeschränkung an dem noch nicht geladenen Modul, auf das Bezug genommen wird, oder Modulen neu geschrieben wird. Der Schritt 885 schreibt die Vorverifizierungsbeschränkung neu als eine Verifizierungsbeschränkung nur an die noch nicht geladenen Module, auf die Bezug genommen wird, wie beispielsweise Klassen. Nach dem erneuten Schreiben, wenn es nötig ist, geht die Steuerung zum Schritt 878.

Modul-für-Modul-Verifizierung von nicht vertrauenswürdigen Klassen

Wie es oben angegeben ist, beruht eine Verifizierung gemäß der vorliegenden Erfindung auf der Fähigkeit zum Bilden und Kommentieren eines Moduls mit Beschränkungen, die durch Module, auf die Bezug genommen wird, erfüllt werden müssen. Unglücklicherweise verhindern die Prozeduren nicht immer, dass ein Angreifer solche Anmerkungen bzw. Kommentare beschwindelt bzw. parodiert – was möglicherweise eine bösartige Klasse gutartig erscheinen lässt. Daher ist die optionale Vertrauensprüfung in 7C bei einem Schritt 783 und in 8 bei einem Schritt 883 gemäß einem Ausführungsbeispiel der vorliegenden Erfindung enthalten. Bei Abwesenheit dieser Prüfungen kann eine Vorverifizierung in vertrauenswürdigen Situationen verwendet werden, wie beispielsweise dort, wo die Klassen vor einer Ausführung vorverifiziert und in eine vertrauenswürdige (fälschungssichere) Datenbank geladen werden können.

In nicht vertrauenswürdigen Situationen ist jedoch mehr Schutz nötig. Gemäß einem Ausführungsbeispiel der vorliegenden Erfindung wird ein Cache erzeugt, wie es in 9 gezeigt ist. Der Cache 920 würde vertrauenswürdige Module enthalten, wie beispielsweise vertrauenswürdige Klassen und/oder Vorverifizierungsbeschränkungen, z.B. 965a. Module und/oder Beschränkungen, die zu einer virtuellen Maschine von einer nicht vertrauenswürdigen Quelle importiert sind, wie beispielsweise einer Quelle im Internet, würden außerhalb des Caches, z.B. bei 965, platziert werden. Irgendwelche Vorverifizierungsbeschränkungen, die mit der Klasse von der nicht vertrauenswürdigen Quelle kommen, wie z.B. 965, würden ignoriert werden. Statt dessen wird das erste Mal, wenn ein solches Modul geladen wird, es in einem Vorverifizierer 910 eifriger vorverifiziert, und zwar gemäß dem in 7A gezeigten Verfahren. Wenn das Modul bezüglich einer Vorverifizierung fehlschlägt, wird es sofort zurückgewiesen werden. Wenn das Modul bezüglich der Vorverifizierung nicht fehlschlägt, werden neue Vorverifizierungsbeschränkungen erzeugt, wie es nötig ist, und dann wird das Modul, kommentiert oder verbunden mit den neuen Beschränkungen, z.B. 965a, in einem Cache 920 für ein vertrauenswürdiges Modul gespeichert. Bei darauf folgenden Versuchen zum Laden des Moduls von einer nicht vertrauenswürdigen Quelle wird zuerst der Modulcache 920 durchsucht werden. Wenn das im Cache gespeicherte, vorverifizierte Modul 965a gefunden wird, kann dann das Modul 965a sicher als vorverifiziert verwendet werden. Mit dieser Modifikation wird eine Prüfung von Klasse-für-Klasse-Vorverifizierungsbeschränkungen, wie es in 7B gezeigt ist, richtig fortschreiten. Effektiv beantwortet der Schritt 780 der 7C die Frage diesbezüglich, ob eine Vorverifizierung durchgeführt worden ist, indem der Modulcache geprüft wird. Mit dieser Modifikation ist das digitale Signieren der Vorverifizierungsbeschränkungen, Schritt 718 in 7A, nicht nötig. Gleichermaßen ist mit dieser Modifikation die Prüfung diesbezüglich, ob die Vorverifizierungsausgabe vertrauenswürdig ist, welche im Schritt 783 der 7C und im Schritt 883 der 8 gezeigt ist, ebenso nicht nötig, und der Ablauf geht direkt vom Schritt 780 oder 880 jeweils direkt weiter zum Schritt 784 oder 884.

Formen von Beschränkungen

Die in Ablaufdiagrammen in den 6A, 6C, 7A, 7B und 8 dargestellten Verfahren stellen alle Elemente zum Prüfen von Klassen, auf die Bezug genommen wird, so spät wie möglich zur Verfügung. Die Form der geschriebenen Beschränkungen und die Art, auf welche diese Beschränkungen darauf folgend geprüft werden, ist wie folgt. Die Beschränkungen können beispielsweise im Schritt 650 der 6A, im Schritt 750 der 7B und in den Schritt 885 und 889 der 8 geschrieben werden. Ein Erzwingen der Beschränkungen kann im Schritt 673 der 6C und im Schritt 788 der 7C und im Schritt 888 der 8 angewendet werden.

Eine Beschränkungserzeugung und ein Prüfen der Beschränkung werden detaillierter durch ein Beispiel beschrieben werden. Gemäß 2 gibt die Zuordnungsangabe an, dass ein neuer Fall der Klasse B in der Variablen var des Klassentyps A gespeichert werden wird. In einer objektorientierten Sprache erfordert diese Zuordnung, dass B ein Untertyp der Klasse A ist, wie es durch den Ausdruck B ≤ A dargestellt ist. Dies ist während einer Verifizierung von BAR nicht bekannt, wenn B zu dieser Zeit nicht geladen ist. Wenn B geladen ist und B eine Unterklasse von A ist, dann muss auch A geladen werden (weil A geladen werden musste, um B zu laden). Daher ist das Gegensätzliche wahr, d.h. dass dann, wenn B geladen ist und A nicht geladen ist, B keine Unterklasse von A ist; die Zuordnungsangabe veranlasst eine Untertypisierungsfehlanpassung, welche veranlasst, dass die Klasse BAR bezüglich einer Verifizierung fehlschlägt. Wenn sowohl A als auch B geladen sind, wie bei einem eifrigeren Laden, das in 3 gezeigt ist, dann kann der Indikator der Superklasse für B verfolgt werden, um zu sehen, ob A irgendwo eine Superklasse von B ist. Wenn es so ist, ist B eine Unterklasse von A und diese Zuordnung durchläuft eine Verifizierung. Wenn A durch Verfolgen der Superklassenindikatoren die Hierarchie hinauf nicht gefunden wird, dann ist B keine Unterklasse von A; die Zuordnungsangabe verursacht eine Untertypisierungsfehlanpassung und die Klasse BAR schlägt bezüglich einer Verifizierung fehl.

Unter Verwendung der herkömmlichen JVM-Spezifikation würde der Verifizierer, wenn die Klasse B nicht bereits geladen wäre, die Klasse B laden und ihren Typ prüfen, und zwar insbesondere, ob er ein Untertyp der Klasse A ist.

Gemäß der vorliegenden Erfindung ist es zum Erreichen eines vollständig trägen Ladens oder einer Klasse-für-Klasse-Verifizierung, oder von beidem, erwünscht, die Klasse B nicht zu laden. Daher wird gemäß diesem Ausführungsbeispiel der vorliegenden Erfindung B nicht geladen; und statt dessen wird eine Beschränkung B <= A geschrieben. Diese Beschränkung kann in irgendeinem der Schritte geschrieben werden, die oben zum Schreiben von Beschränkungen aufgelistet ist (z.B. 650, 750, 889, 885). Später, nämlich dann, wenn BAR.FOO ausgeführt wird, wenn dieser Zweig mit der Zuordnungsangabe nicht ausgeführt wird und auf B nicht gleichermaßen von irgendeiner anderen Anweisung Bezug genommen wird, die ausgeführt wird, wird die Klasse B niemals geladen. Aber dann, wenn der Zweig, der diese Zuordnungsangabe enthält, ausgeführt wird und B nicht geladen ist, wird die Klasse B zu dieser Zeit geladen werden; und zu dieser Zeit wird, nachdem die Klasse B geladen ist, die Prüfung diesbezüglich durchgeführt werden, ob die Klasse B die Beschränkung <= A erfüllt. Dieses Prüfen kann wie beispielsweise in den Schritten durchgeführt werden, die oben zum Prüfen von Beschränkungen aufgelistet sind (z.B. 673, 788, 888). Dies wird einfach durchzuführen sein, weil dann, wenn die Klasse B tatsächlich eine Unterklasse der Klasse A ist und ihre Attribute von der Klasse A als eigene hat, würde die Klasse A bereits geladen worden sein müssen. Somit lässt eine Beschränkung von diesem Typ ein vollständig träges Laden, eine Klasse-für-Klasse-Vorverifizierung oder beides zu.

Es gibt eine weitere Prüfung bezüglich eines Klassentyps von nicht lokalen Klassen, die bei einer Klasse-für-Klasse-Vorverifizierung anders behandelt werden können, als es bei der Implementierung des vollständig trägen Ladens behandelt wird, und zwar gemäß der vorliegenden Erfindung. Dies ist die Empfängerzugriffsprüfung für geschützte Elemente.

In der virtuellen JAVATM-Maschine kann auf ein geschütztes Element R durch eine Klasse oder eine Schnittstelle D zugegriffen werden, wenn und nur wenn:

  • 1. D in demselben Laufzeitpaket wie die Klasse C ist, die R ODER BEIDES deklarierte.
  • 2. D eine Unterklasse von C ist, nämlich der Klasse, die R deklarierte, UND
  • 3. wenn R ein Fallelement ist, dann ist T, nämlich der statische Typ des Falls R, auf was zugegriffen wird, ein Untertyp von D.

Die 3. Anforderung ist als die empfängergeschützte Prüfung bekannt.

In einer herkömmlichen virtuellen JAVATM-Maschine werden die ersten zwei Anforderungen geprüft, wenn die Referenz von D zu R während eines Bindens von D aufgelöst wird, während die dritte Anforderung während einer Verifizierung von D geprüft wird. Während einer Verifizierung kann es sein, dass die Klasse C, die R deklariert, noch nicht geladen worden ist. In diesem Fall ist es offensichtlich, dass C keine Superklasse von D ist (sonst würde C per Zwang geladen worden sein, weil ein Laden einer Klasse das Laden von allen ihren Superklassen impliziert). In diesem Fall ist der Zugriff nur dann legal, wenn C und D im selben Laufzeitpaket sind. Der Verifizierer kann optimistisch annehmen, dass dies gilt. Die Anforderung wird geprüft werden, wenn die Referenz aufgelöst wird. Somit muss der Verifizierer nur die geschützte Empfängerprüfung durchführen, wenn C bereits geladen worden ist. In dieser Situation ist es möglich, zu bestimmen, ob R überhaupt ein geschütztes Element ist. Wenn R nicht geschützt ist, ist keine geschützte Empfängerprüfung nötig. Wenn R geschützt ist, kann der Vorverifizierer testen, um zu sehen, ob D im selben Laufzeitpaket wie C ist. Wenn dies der Fall ist, ist der Zugriff legal, und wiederum ist keine geschützte Empfängerprüfung nötig. Wenn D und C nicht im selben Laufzeitpaket sind, kann der Verifizierer prüfen, ob D eine Unterklasse von C ist und ob T, der statische Typ des Falls, auf den zugegriffen wird, ein Untertyp von D ist. Wenn es nicht so ist, wird ein Fehler veranlasst. Es ist zu beachten, dass die Prüfung T <= D ein Laden von T erfordern kann, wenn es nicht bereits geladen worden ist.

Bei einer Verifizierung mit einem vollständig trägen Laden wird beim Verifizieren von D angenommen, dass ihre Superklasse geladen worden ist. Eine Steuerung geht auf dieselbe Weise wie in dem nicht trägen Fall weiter, mit einer Ausnahme. Wenn bestimmt wird, dass eine Prüfung, ob T <= D gilt, nötig ist, und T nicht geladen ist, muss ein Laden vermieden werden. Statt dessen wird die Ladebeschränkung T <= D t auferlegt.

Bei einer Klasse-für-Klasse-Verifizierung ist die Situation anders. Weder die Superklasse von D noch die Klasse C, die R deklarierte, sind geladen worden. Daher kann die geschützte Empfängerprüfung nicht durchgeführt werden. Die Annahme, dass dann, wenn C eine Superklasse von D ist, sie geladen worden sein muss, kann nicht gemacht werden, und somit kann die Deklaration von R nicht untersucht werden. Es folgt, dass es sogar nicht bestimmt werden kann, ob R geschützt ist oder nicht. Statt dessen müssen geeignete Beschränkungen erzeugt werden, die zu einer späteren Zeit geprüft werden, wenn das Programm ausführt. Dieses Problem kann durch Erzeugen der Bedingungsbeschränkung gelöst werden: Wenn (D <= X), dann {wenn (X.m geschützt) dann {T <= D}, sonst {wahr}} sonst {wahr} für jede Anweisung der Form:

o,X.m aufrufen,

wobei o den Typ T hat. Eine gleiche Strategie gilt für Feldreferenzen. Diese Beschränkung wird vor der Initialisierung von D untersucht. An dieser Stelle kann über D <= X entschieden werden (da D und alle ihre Superklassen bereits geladen worden sind). Wenn D <= X nicht wahr ist, ist keine weitere Aktion nötig. Wenn D keine Unterklasse von X ist, dann kann D möglicherweise eine Unterklasse von C sein, nämlich der Klasse, die m deklarierte. Der Grund dafür ist, dass C notwendigerweise eine Superklasse von X sein muss. Es folgt, dass die Referenz auf X.m nur legal ist, wenn entweder m nicht geschützt ist oder C im selben Laufzeitpaket wie D ist. Dies wird geprüft werden, wenn die Referenz auf X.m aufgelöst wird. Wenn es wahr ist, dass D <= X, dann kann geprüft werden, ob X.m geschützt ist oder nicht. Wenn X.m nicht geschützt ist, muss die geschützte Empfängerprüfung nicht durchgeführt werden. Sonst kann der Test, ob T <= D durchgeführt werden, welcher, wie oben, veranlassen kann, dass T geladen wird.

Wenn eine vollständig träge Verifizierung mit einer Klasse-für-Klasse-Verifizierung kombiniert wird, wird der Prozedur für eine Klasse-für-Klasse-Verifizierung gefolgt, außer dann, wenn die folgende Bedingungsbeschränkung ausgewertet wird:

wenn (D <= X) dann {wenn(X.m geschützt), dann {T <= D}, sonst {wahr}}, sonst {wahr},

wenn man T <= D auswerten muss und wenn T nicht geladen ist, sollte man T die Ladebeschränkung T <= D auferlegen, wie im trägen Fall.

Eine weitere Beschränkung ist dann geeignet, wenn eine Verifizierung den Zustand des Operandenstapels bei einer Angabe untersucht, die eine Nachfolgerangabe zu mehreren früheren ausgeführten Angaben ist, d.h. wo zwei oder mehrere Zweige konvergieren. An dieser Stelle ist die Verifizierung gegenwärtig derart entwickelt, dass die Momentaufnahmen des Operandenstapels und von lokalen Variablen von den vorangehenden Anweisungen verknüpft werden zu welchen die aktuelle Anweisung ein Nachfolger ist. Wenn die Referenzen zu Typen erfolgen, die in Klassen definiert sind, die noch nicht geladen sind, was immer der Fall bei einer Klasse-für-Klasse-Vorverifizierung sein wird und manchmal der Fall bei einem vollständig trägen Laden, ist das Typengitter nicht verfügbar und ist die LUB nicht bekannt. Der für den Schritt 638 der 6B oben beschriebenen symbolischen Darstellung einer LUB folgend kann eine Beschränkung, wie beispielsweise "LUB <= Klasse T" durch eine Beschränkung auf einer Liste ersetzt werden, die symbolisch dargestellt ist als: X1^X2^...Xn <= T

Dies kann in eine Reihe von Beschränkungen von individuellen Klassen von X; faktorisiert werden, wie es folgt: X1 <= T, X2 <= T,..., Xn <= T.

Wenn das aktuelle Verfahren einer geladenen Klasse ausgeführt wird und durch einen Zweig geht, der eine Auflösung der Klasse X2 als Beispiel erfordert, dann wird die Klasse X2 geladen und kann die Beschränkung X2 <= T zu dieser Zeit geprüft werden. Alternativ dazu kann eine Beschränkung auf der Liste durch Fallenlassen von X2 aus der Liste neu geschrieben werden, wenn X2 die Prüfung durchläuft, wenn X2 geladen wird.

Wie es oben beschrieben ist, werden die Beschränkungen während irgendwelcher von mehreren Schritten (z.B. 650, 750, 889, 885) geschrieben und werden die Beschränkungen dann bei irgendwelchen der mehreren Prüfschritte (z.B. 673, 788, 888) geprüft.

Mit dieser symbolischen Darstellung der LUB kann es länger dauern, bis die aktuellen Berechnungen konvergieren. Jedoch wird garantiert, dass der Prozess konvergiert, weil der konstante Pool einer Klassendatei der JVM endlich ist. Somit kann nur auf eine endliche Anzahl von Typen durch ein Verfahren direkt oder indirekt Bezug genommen werden. Als Ergebnis muss die symbolische Darstellung einer LUB eine endliche Sequenz von Klassennamen X1^...^Xn sein. Infolge davon bedeutet dies, dass die Anzahl von Iterationen durch den Typeninferenzalgorithmus für die JVM endlich ist, da Iterationen fortfahren, bis keine neuen Typen zu der LUB hinzugefügt werden können.


Anspruch[de]
  1. Verfahren für eine vertrauenswürdige Verifizierung von Anweisungen in einem Modul eines Computerprogramms, wobei das Verfahren folgendes aufweist:

    Bestimmen, ob ein zu ladendes verdächtiges Modul von einer nicht vertrauenswürdigen Quelle ist;

    Laden des verdächtigen Moduls und Durchführen einer Vorverifizierung für ein Modul pro Zeiteinheit an dem verdächtigen Modul vor einem Binden basierend auf einer Bestimmung, dass das verdächtige Modul von einer nicht vertrauenswürdigen Quelle ist, wobei die Vorverifizierung folgendes aufweist: Bestimmen, ob eine Anweisung in dem verdächtigen Modul Information in einem bezogenen Modul erfordert, das ein anderes als das verdächtige Modul ist, Schreiben einer Vorverifizierungsbeschränkung für das bezogene Modul in einem vertrauenswürdigen Cache, ohne einen Zugriff auf das bezogene Modul zu erfordern, basierend auf einer Bestimmung, dass die Information erforderlich ist, und Prüfen der Anweisung unter der Annahme, dass die Vorverifizierungsbeschränkung erfüllt ist; und

    Speichern des verdächtigen Moduls in einem vertrauenswürdigen Cache, wenn das verdächtige Modul die Vorverifizierung durchläuft.
  2. Verfahren nach Anspruch 1, das während eines Bindens weiterhin folgendes aufweist:

    Bestimmen, ob ein erstes Modul eine Vorverifizierung für ein Modul pro Zeiteinheit durchlaufen hat;

    wenn das erste Modul eine Vorverifizierung durchlaufen hat, Bestimmen, ob Ergebnisse vertrauenswürdig sind;

    wenn die Ergebnisse vertrauenswürdig sind, Lesen einer Vorverifizierungsbeschränkung über ein beschränktes Modul, wenn irgendeine existiert;

    wenn irgendeine Vorverifizierungsbeschränkung existiert, Bestimmen, ob das beschränkte Modul geladen ist; und

    wenn das beschränkte Modul geladen ist, Geltend machen der Vorverifizierungsbeschränkung.
  3. Verfahren nach Anspruch 2, wobei der Schritt zum Bestimmen, ob die Ergebnisse vertrauenswürdig sind, ein Finden von Beschränkungen im vertrauenswürdigen Cache aufweist.
  4. Verfahren nach Anspruch 2 oder 3, wobei der Schritt zum Bestimmen, ob die Ergebnisse vertrauenswürdig sind, ein Finden des ersten Moduls im vertrauenswürdigen Cache aufweist.
  5. Verfahren nach Anspruch 2, wobei der Schritt zum Bestimmen, ob die Ergebnisse vertrauenswürdig sind, ein Prüfen einer digitalen Signatur aufweist.
  6. Verfahren nach einem der Ansprüche 2 bis 5, das dann, wenn dem bezogene Modul die Vorverifizierungsbeschränkung fehlt, weiterhin ein Schreiben einer Fehlernachricht aufweist.
  7. Computerprogrammprodukt für eine vertrauenswürdige Verifizierung von Anweisungen in einem Modul eines Computerprogramms, wobei das Computerprogramm folgendes aufweist:

    ein computerlesbares Speichermedium; und

    Computersteuerbefehle, die auf dem computerlesbaren Speichermedium gespeichert sind, zum Bestimmen, ob ein zu ladendes verdächtiges Modul von einer nicht vertrauenswürdigen Quelle ist; zum Laden des verdächtigen Moduls und zum Durchführen einer Vorverifizierung für ein Modul pro Zeiteinheit an dem verdächtigen Modul vor einem Binden basierend auf einer Bestimmung, dass das verdächtige Modul von einer nicht vertrauenswürdigen Quelle ist, wobei die Vorverifizierung folgendes aufweist: Bestimmen, ob eine Anweisung in dem verdächtigen Modul eine Information in einem bezogenen Modul erfordert, das ein anderes als das verdächtige Modul ist, Schreiben einer Vorverifizierungsbeschränkung für das bezogene Modul in einem vertrauenswürdigen Cache, ohne einen Zugriff auf das bezogene Modul zu erfordern, basierend auf einer Bestimmung, dass die Information erforderlich ist, und Prüfen der Anweisung unter der Annahme, dass die Vorverifizierungsbeschränkung erfüllt ist; und zum Speichern des Moduls in einem vertrauenswürdigen Cache, wenn das verdächtige Modul die Vorverifizierung durchläuft.
  8. Computerprogrammprodukt nach Anspruch 7, das weiterhin Computersteuerbefehle aufweist, die während eines Bindens konfiguriert sind,

    um zu bestimmen, ob ein erstes Modul eine Vorverifizierung für ein Modul pro Zeiteinheit durchlaufen hat;

    wenn das erste Modul eine Vorverifizierung durchlaufen hat, um zu bestimmen, ob Ergebnisse vertrauenswürdig sind;

    wenn die Ergebnisse vertrauenswürdig sind, um eine Vorverifizierungsbeschränkung über ein beschränktes Modul zu lesen, wenn irgendeine existiert;

    wenn irgendeine Vorverifizierungsbeschränkung existiert, um zu bestimmen, ob das beschränkte Modul geladen ist; und

    wenn das beschränkte Modul geladen ist, um die Vorverifizierungsbeschränkung geltend zu machen.
  9. Computerprogrammprodukt nach Anspruch 8, das weiterhin Computersteuerbefehle aufweist, die auf dem computerlesbaren Speichermedium gespeichert sind, zum Bestimmen, ob Ergebnisse vertrauenswürdig sind, durch Finden von Beschränkungen in dem vertrauenswürdigen Cache.
  10. Computerprogrammprodukt nach Anspruch 8, das weiterhin Computersteuerbefehle aufweist, die auf dem computerlesbaren Speichermedium gespeichert sind, zum Bestimmen, ob Ergebnisse vertrauenswürdig sind, durch Prüfen einer digitalen Signatur.
  11. Computerprogrammprodukt nach Anspruch 8, das weiterhin Computersteuerbefehle aufweist, die auf dem computerlesbaren Speichermedium gespeichert sind, zum Schreiben einer Fehlernachricht, wenn dem bezogenen Modul die Vorverifizierungsbeschränkung fehlt.
  12. Vertrauenswürdige Verifizierervorrichtung für eine vertrauenswürdige Verifizierung von Anweisungen in einem Modul eines Computerprogramms, wobei der vertrauenswürdige Verifizierer folgendes aufweist:

    ein computerlesbares Speichermedium zum Speichern eines Moduls eines Computerprogramms;

    einen Speicher, in welchen ein Modul geladen ist; und

    einen Prozessor, der konfiguriert ist, um zu bestimmen, ob ein zu ladendes verdächtiges Modul von einer nicht vertrauenswürdigen Quelle ist; um das verdächtige Modul zu laden und um eine Vorverifizierung für ein Modul pro Zeiteinheit an dem verdächtigen Modul vor einem Binden basierend auf einer Bestimmung durchzuführen, dass das verdächtige Modul von einer nicht vertrauenswürdigen Quelle ist, wobei die Vorverifizierung folgendes aufweist: Bestimmen, ob eine Anweisung in dem verdächtigen Modul Information in einem bezogenen Modul erfordert, das ein anderes als das verdächtige Modul ist, Schreiben einer Vorverifizierungsbeschränkung für das bezogene Modul in einem vertrauenswürdigen Cache, ohne einen Zugriff auf das bezogene Modul zu erfordern, basierend auf einer Bestimmung, dass die Information erforderlich ist, und Prüfen der Anweisung unter der Annahme, dass die Vorverifizierungsbeschränkung erfüllt ist; und um das Modul in einem vertrauenswürdigen Cache zu speichern, wenn das verdächtige Modul die Vorverifizierung durchläuft.
  13. Signalübertragung, die folgendes aufweist:

    eine Trägerwelle auf einer Kommunikationsleitung; und

    Signale, die Computersteuerbefehle anzeigen, die unter Verwendung der Trägerwelle gesendet bzw. übertragen werden, zum Bestimmen, ob ein zu ladendes verdächtiges Modul von einer nicht vertrauenswürdigen Quelle ist, zum Laden des verdächtigen Moduls und zum Durchführen einer Vorverifizierung für ein Modul pro Zeiteinheit an dem verdächtigen Modul vor einem Binden basierend auf einer Bestimmung, dass das verdächtige Modul von einer nicht vertrauenswürdigen Quelle ist, wobei die Vorverifizierung folgendes aufweist: Bestimmen, ob eine Anweisung in dem verdächtigen Modul Information in einem bezogenen Modul erfordert, das ein anderes als das verdächtige Modul ist, Schreiben einer Vorverifizierungsbeschränkung für das bezogene Modul in einem vertrauenswürdigen Cache, ohne einen Zugriff auf das bezogene Modul zu erfordern, basierend auf einer Bestimmung, dass die Information erforderlich ist, und Prüfen der Anweisung unter der Annahme, dass die Vorverifizierungsbeschränkung erfüllt ist, und zum Speichern des Moduls in einem vertrauenswürdigen Cache, wenn das verdächtige Modul die Vorverifizierung durchläuft.
  14. Signalübertragung nach Anspruch 13, wobei die Signale folgendermaßen angeordnet sind:

    zum Bestimmen, ob ein erstes Modul eine Vorverifizierung für ein Modul pro Zeiteinheit durchlaufen hat;

    wenn das erste Modul eine Vorverifizierung durchlaufen hat, zum Bestimmen, ob Ergebnisse vertrauenswürdig sind;

    wenn die Ergebnisse vertrauenswürdig sind, zum Lesen einer Vorverifizierungsbeschränkung über ein beschränktes Modul, wenn irgendeine existiert;

    wenn irgendeine Vorverifizierungsbeschränkung existiert, zum Bestimmen, ob das beschränkte Modul geladen ist; und

    wenn das beschränkte Modul geladen ist, zum Geltend machen der Vorverifizierungsbeschränkung.
  15. Signalübertragung nach Anspruch 14, die weiterhin Computersteuerbefehle aufweist, die unter Verwendung der Trägerwelle übertragen werden, zum Bestimmen, ob Ergebnisse vertrauenswürdig sind, durch Finden von Beschränkungen im vertrauenswürdigen Cache.
  16. Signalübertragung nach Anspruch 14, die weiterhin Computersteuerbefehle aufweist, die unter Verwendung der Trägerwelle übertragen werden, zum Bestimmen, ob Ergebnisse vertrauenswürdig sind, durch Prüfen einer digitalen Signatur.
  17. Signalübertragung nach Anspruch 14, die weiterhin Computersteuerbefehle aufweist, die unter Verwendung der Trägerwelle übertragen werden, zum Schreiben einer Fehlernachricht, wenn dem bezogenen Modul die Vorverifizierungsbeschränkung fehlt.
Es folgen 18 Blatt Zeichnungen






IPC
A Täglicher Lebensbedarf
B Arbeitsverfahren; Transportieren
C Chemie; Hüttenwesen
D Textilien; Papier
E Bauwesen; Erdbohren; Bergbau
F Maschinenbau; Beleuchtung; Heizung; Waffen; Sprengen
G Physik
H Elektrotechnik

Anmelder
Datum

Patentrecherche

  Patente PDF

Copyright © 2008 Patent-De Alle Rechte vorbehalten. eMail: info@patent-de.com