Memory Inspector: Konzepte 
Für die Arbeit mit Memory Inspector ist ein Verständnis der folgenden Konzepte hilfreich.
Ein Speicherabzug erfasst den Speicherverbrauch des internen Modus, in dem ein ABAP-Programm läuft.
Angezeigt werden:
Der direkt der ABAP-Anwendung zuordenbare verbrauchte Speicher. Dazu zählt der Speicher in statischen und dynamischen Speicherobjekten des ABAP-Programms sowie der vom Programm im ABAP-Stack verwendete Speicher.
Der allokierte Speicher in Bezug auf das Host-Betriebssystem für den internen Modus insgesamt. Dazu zählt der ABAP-Speicherverbrauch sowie die relativ kleine Speichermenge, die von der ABAP-Laufzeit und der Verwaltung der internen Modi verbraucht wird.
Vor dem Erstellen eines Speicherabzugs wird in Memory Inspector regelmäßig ABAP Garbage Collector ausgeführt, damit tote Speicherobjekte nicht die ermittelten Speicherverbrauchszahlen verzerren.
Im Allgemeinen und im Besonderen wegen des geringen Overhead für die Ausführung eines internen Modus ist bei der Analyse von Speicherproblemen ausschließlich der Speicher interessant, welcher der ABAP-Anwendung zugerechnet werden kann. Als Entwickler haben Sie generell ausschließlich Einfluss auf den Speicherverbrauch des ABAP-Programms, nicht jedoch auf den Verbrauch des Laufzeitsystems.
Von allen ABAP-Speicherobjekttypen sind die dynamischen Speicherobjekte diejenigen, die am wahrscheinlichsten zu Problemen führen. Dynamische Speicherobjekte sind Objekte, deren Größe sich während der Laufzeit des Programms ändern kann. Zu den dynamischen Speicherobjekten gehören die folgenden ABAP-Entitätstypen:
Interne Tabellen (bzw. die Zeilen in einer internen Tabelle, d.h. der Tabellenkörper)
Klassenobjekte (Objekte, die durch die Anweisung CREATE OBJECT erstellt werden)
Anonyme Datenobjekte (Objekte, die durch die Anweisung CREATE DATA erstellt werden)
Boxed Components
Eine Variable für den Zugriff auf ein dynamisches Speicherobjekt enthält eine Referenz auf eine interne Speicherstruktur, in der die Daten des dynamischen Speicherobjekts gehalten werden. Variablen für dynamische Speicherobjekte werden daher allgemein als Referenzvariablen bezeichnet. (In ABAP werden referenzierte Programmentitäten als 'tiefe Komponenten' bezeichnet, d.h. Komponenten, auf deren Inhalt über die Auswertung einer Referenz zugegriffen werden muss.)
Statische Speicherobjekte (Statische Variablen in den Memory-Inspector-Sichten) sind hingegen Objekte, deren Größe zur Designzeit von der Datentypdeklaration festgelegt wird. Der von solchen Variablen in einem Programm belegte Speicher kann nur dann geändert werden, wenn der Programmquelltext selbst modifiziert wird.
Die Wertesemantik und die Referenzsemantik stellen zwei mögliche Verhaltensweisen eines dynamischen Speicherobjekts dar, wenn mehr als eine Variable auf das Objekt verweist.
Die für einen bestimmten Typ dynamischer Speicherobjekte verwendete Semantik wirkt sich erheblich auf die Art und Weise aus, wie Objekte dieses Typs Speicher verbrauchen.
In diesem Abschnitt wird erläutert, welche Semantik für welche Speicherobjekttypen in ABAP gilt und wie die Semantik den Speicherverbrauch beeinflusst.
Grundsätzlich verfügt eine Referenzvariable, welche die Wertesemantik verwendet, über eine eigene eindeutige Kopie des Speicherobjekts, das sie referenziert. Eine Wertesemantikvariable ähnelt einer statischen Variable; wie eine statische Variable ist sie direkt an das von ihr repräsentierte Speicherobjekt gebunden. Auch wenn die Variable nur eine Referenz ist, IST sie semantisch gesehen das Speicherobjekt selbst.
Eine Referenzvariable, welche hingegen die Referenzsemantik verwendet, wird als Zeiger auf ein Speicherobjekt interpretiert. Das Speicherobjekt ist semantisch unabhängig von der Referenzvariablen. Das Objekt kann von vielen solcher Variablen gleichzeitig genutzt werden.
Mehrfachreferenzen auf interne ABAP-Tabellen, ABAP-Strings oder ABAP-Boxed-Components werden über die Wertesemantik aufgelöst. Dies bedeutet Folgendes:
Jede Variable für eine interne Tabelle, einen String oder eine Boxed Component zeigt auf ihre eigene persönliche Kopie des Speicherobjekts.
Wird eine Tabelle, ein String oder eine Boxed Component einer weiteren ABAP-Variable zugewiesen, wird ein Kopiervorgang des Objekts angestoßen, so dass wiederum jede Variable über eine eigene Kopie des Objekts verfügt.
Änderungen, die über eine bestimmte Variable an einer internen Tabelle, einem String oder einer Boxed Component vorgenommen werden, sind für andere Variablen, die dem gleichen Objekt zugewiesen sind, nicht sichtbar.
Da interne Tabellen und Strings relativ groß werden können, wird in ABAP versucht, die durch den Kopiervorgang erzeugte Last durch bedarfsgetriebenes Kopieren (Copy-On-Write) möglichst gering zu halten. Den gleichen Effekt hat das Initialwert-Sharing bzw. der erneute Aufruf des Initialwert-Sharing bei statischen Boxed Components.
Solange die Komponente nicht geändert wird, zeigen alle Variablen mit Bezug auf die Tabelle bzw. den String auf ein einzelnes Speicherobjekt. Nur wenn eine Tabelle bzw. ein String über eine Variable geändert wird, erstellt die ABAP-Laufzeit eine eigene Kopie des geänderten Objekts. Dieses sogenannte bedarfsgetriebene Kopieren bedeutet, dass Änderungen an Tabellen, Strings oder Boxed Components zu überraschenden Sprüngen im Speicherverbrauch führen, wie aus Memory Inspector ersichtlich wird.
ABAP erfasst die Variablen mit Bezug auf eine Tabelle, einen String oder eine Boxed Component mit Hilfe eines Referenzzählers. Da diese Entitäten nur dann existieren, wenn sie einen Referenzzähler von mindestens 1 haben, werden diese Objekte von ABAP Garbage Collector ignoriert (es sei denn, sie gehören zum gebundenen Speicher eines zu löschenden Klassenobjekts). Entweder wird ein String oder eine Tabelle von mindestens einer Variable referenziert, oder der String bzw. die Tabelle wurde gelöscht.
Der Referenzzähler bestimmt auch, ob eine Tabelle oder ein String zum gebundenen Speicher des referenzierenden Objekts gerechnet wird. Nur wenn der Zähler auf 1 steht - d.h. das referenzierte Objekt gehört exklusiv zum referenzierenden Objekt - zählt das referenzierte Objekt zum gebundenen Speicher.
Beispiel
Wertesemantik in ABAP: Variable T1 repräsentiert eine interne Tabelle. Sie weisen die interne Tabelle auch zu Variable T2 zu.
DATA t1 TYPE STANDARD TABLE OF xyz.
DATA t2 TYPE STANDARD TABLE OF xyz.
DATA t_wa type xyz.
...
t2[] = t1[].
Semantisch gesehen verfügen T1 und T2 über ihre eigene persönliche Kopie der internen Tabelle. Aufgrund des bedarfsgetriebenen Kopieansatzes von ABAP zeigen T1 und T2 momentan beide auf eine einzige interne Tabelle im Speicher. Wenn die Tabelle 1000 Zeilen mit einer Länge von 20 Byte hat, dann zeigt ein zum jetzigen Zeitpunkt erstellter Speicherabzug Speicher von 20 KB für dynamische Objekte, also von der Größe einer Tabelle.
Wenn Sie nun den Arbeitsbereich T_WA an eine der Tabellen anhängen, zeigt der nächste Abzug, dass sich der Speicher für dynamische Objekte mehr als verdoppelt hat.
APPEND t_wa TO t1.
Ursache: Die Änderung an T1 bedeutet, dass die ABAP-Laufzeit die Erstellung der Tabellenkopie für T2 abschließen musste. Jede Variable hat nun ihr eigenes persönliches dynamisches Speicherobjekt. Die Tabelle von T1 hat ebenfalls eine Zeile mehr als die Tabelle von T2.
Beim Auftreten des APPEND hat die ABAP-Laufzeit erkannt, dass der Referenzzähler auf die Tabelle den Wert 2 hatte und dass das dynamische Speicherobjekt (der Tabellenkörper) kopiert werden musste. Nach dem APPEND hatte jede Kopie der Tabelle einen Referenzzählerwert von 1.
Mehrfachreferenzen auf Instanzen von ABAP-Klassen (Klassenobjekte) oder anonyme Datenobjekte werden über die Referenzsemantik aufgelöst. Dies bedeutet Folgendes:
Alle Variablen mit Bezug auf ein einzelnes Klassenobjekt oder anonymes Datenobjekt nutzen eine einzige Kopie des Objekts im Speicher gemeinsam. Wenn ein solches Objekt einer neuen Variablen zugewiesen wird, wird eine Referenz und nie eine eigene Kopie des referenzierten Speicherobjekts erstellt.
Änderungen an einem Klassenobjekt oder anonymen Datenüberobjekt über eine bestimmte Variable sind für alle anderen Variablen mit Bezug auf dieses Objekt sichtbar.
Anders als Tabellen, Strings und Boxed Components können Instanzen von Klassen oder anonyme Datenobjekte sich nicht unvermittelt selbst als separate Speicherobjekte manifestieren, wenn Referenzen hinzugefügt werden und ein Objekt geändert wird.
Klassenobjekte und anonyme Datenobjekte verfügen nicht über Referenzzähler. Da es nicht bekannt ist, ob Referenzen auf ein solches Objekt existieren, bleibt es ABAP Garbage Collector überlassen, nicht mehr referenzierte Speicherobjekte aufzufinden und zu löschen.
Beispiel
Referenzsemantik in ABAP: CO_1 repräsentiert eine Instanz von Klasse CL_1. Sie weisen die Instanz von CL_1 auch zu CO_2 zu.
DATA co_1 TYPE REF TO cl_1.
DATA co_2 TYPE REF TO cl_1.
CREATE OBJECT co_1.
co_2 = co_1.
Die Variablen CO_1 and CO_2 zeigen jetzt beide auf ein einziges Klassenobjekt im Speicher. Sie ändern jetzt den Wert von ATTR1 von Klasse CL_1.
co_1–>attr1 = 'ABC'.
CO_2–>ATTR1 hat jetzt auch den Wert 'ABC'. Beide Variablen beziehen sich weiterhin auf das gleiche Objekt im Speicher.
Der Dominatorbaum und die Ranglisten in der Transaktion Memory Inspector und den Memory-Inspector-Sichten im Debugger beziehen sich auf den gebundenen Speicher. In diesem Abschnitt wird erläutert, was gebundener Speicher ist.
Sie können sich den gebundenen Speicher als den Hauptspeicher vorstellen, der freigegeben wird, wenn eine bestimmte Entität in einem Programm - ein Klassenobjekt, eine Tabelle, ein String usw. - gelöscht wird. Zum gebundenen Speicher zählt der für das Objekt selbst benutzte Speicher sowie der zu Objekten gehörige Speicher, die vom Objekt referenziert und exklusiv verwendet werden.
Beachten Sie, dass anders als bei Memory Inspector in SAP NetWeaver Releases vor 7.0 der angezeigte gebundene Speicher alle Speicherobjekte umfasst, die exklusiv vom betreffenden Speicherobjekt verwendet werden.
Es ist leicht erkennbar, ob ein Wertesemantikobjekt wie eine interne Tabelle zum gebundenen Speicher gehört. Wenn der Referenzzählerwert auf 1 steht, dann zählt das Speicherobjekt zum gebundenen Speicher des referenzierenden Objekts.
Memory Inspector prüft auch die Referenzsemantikobjekte, wie Instanzen von Klassen, um festzustellen, ob die Objekte exklusiv verwendet werden oder ob Mehrfachreferenzen auf die Objekte vorliegen. Handelt es sich um eine einfache Referenz auf ein Referenzsemantikobjekt, dann zählt das Objekt zum gebundenen Speicher des referenzierenden Objekts und wird entsprechend in den Analysesichten von Memory Inspector angezeigt.
Beispiel
Angenommen, für ein Klassenobjekt A gelten folgende Bedingungen:
Klassenobjekt A hat als Attribut eine interne Tabelle und eine Referenz auf ein anderes Klassenobjekt C.
Klassenobjekt A hält die einzigen Referenzen auf die Tabelle und das untergeordnete Objekt C.
In diesem Fall zählen die interne Tabelle und das referenzierte Klassenobjekt zum gebundenen Speicher von Klassenobjekt A. Wenn das Klassenobjekt A gelöscht wird, dann werden die interne Tabelle und das Klassenobjekt C ebenfalls gelöscht.
Wenn die interne Tabelle einen Referenzählerwert von 2 hat und ein weiteres Klassenobjekt B ebenfalls eine Referenz auf das untergeordnete Klassenobjekt C hält, dann umfasst der gebundene Speicher der referenzierenden Klasse nur den vom Klassenobjekt selbst beanspruchten Speicher. Weder die Tabelle noch das untergeordnete Objekt könnten mit dem referenzierenden Klassenobjekt A gelöscht werden. Hinzu kommt, dass Klassenobjekt C nicht gelöscht wird, wenn Klassenobjekt B gelöscht würde. C gehört nicht zum gebundenen Speicher von B oder A.
ABAP muss interne Tabellen und Strings in zusammenhängendem Speicher ablegen. Daher allokiert ABAP immer mehr Speicher für solche Objekte als tatsächlich erforderlich. Dieser zusätzliche Speicher ermöglicht ein effizientes Wachstum von Tabellen und Strings. Ohne den Extraplatz wäre die ABAP-Laufzeit gezwungen, eine Tabelle bzw. einen String in einen größeren zusammenhängenden Speicherbereich zu kopieren, sobald die erste neue Zeile zur Tabelle hinzugefügt bzw. der String erstmals verlängert wird.
Für Strings und interne Tabellen zeigt Memory Inspector sowohl den tatsächlich vom Objekt verwendeten Speicher als auch den für das Objekt allokierten Speicher.
Der allokierte Speicher ist in der Regel größer als der benutzte Speicher und repräsentiert die Speichermenge, die freigemacht würde, wenn eine interne Tabelle oder ein String zurückgesetzt oder gelöscht wird.
ABAP-Klassenobjekte und anonyme Datenobjekte können (im Prinzip) zu starken Zusammenhangskomponenten (SZKs) gehören. Zwei Klassenobjekte, von denen jedes ein Attribut mit Bezug auf das jeweils andere besitzt, bilden bereits eine solche starke Zusammenhangskomponente.
SZKs werden in Memory Inspector in der Sicht Objektzyklen (SZK) abgebildet.
SZKs sind potenziell für die Speicheranalyse wichtig, da eine SZK unnötigerweise eine große Menge Speicher belegen kann. Teilkomponenten einer SZK können nur aus dem Speicher gelöscht werden, wenn die gesamte SZK gelöscht wird. Eine einfache Referenz auf ein beliebiges Objekt in der SZK von außerhalb der SZK hält die gesamte starke Zusammenhangskomponente am Leben.
Wenn Sie auf eine solche große SZK stoßen, sollten Sie das Programmdesign überprüfen. Ist es z.B. wirklich erforderlich, dass Klassenobjekte in einer doppelt verknüpften Liste verwaltet werden? Wenn ja, gibt es Routinen, um nicht mehr benötigte Objekte aus der Liste zu entfernen?
Ein Speicherabzug beinhaltet Informationen über sämtliche Datenobjekte und Instanzen eines internen Modus und deren Speicherverbrauch. Ein Speicherabzug wird im XML-Format in einer Datei auf dem Applikationsserver abgelegt und dort maximal 4 Wochen aufbewahrt. Der Index wird durch den Profilparameter DIR_MEMORY_INSPECTOR bestimmt. Ältere Speicherabzüge werden automatisch und ohne Benutzerdialog gelöscht. Möchten Sie Speicherabzüge länger aufbewahren, können Sie sie während der Anzeige auf den Präsentationsserver laden lassen.
Die Dateinamen der Speicherabzüge werden gemäß folgendem Schema erstellt: abDbgMemory_XX_YYYY, wobei XX die Nummer des aktuellen Workprozesses und YYYY eine laufende Nummerierung innerhalb des aktuellen Workprozesses darstellt. Die Dateinamen sind eindeutig, solange der Workprozess nicht neu gestartet wird. Ab einem Neustart beginnt die Zählung von vorn und bestehende Dateien können überschrieben werden.
Wenn Sie Speicherabzüge vergleichen möchten, sollten Sie die Abzüge vom gleichen internen Modus erstellen - d.h. von einer einzelnen Ausführung des Programms. Ansonsten kann es sein, dass Memory Inspector die Speicherabzüge nicht vergleichen kann.