//

JSP Tag Pooling Memory Leaks

13.8.2009 | 2 Minuten Lesezeit

JSP Custom Tags waren früher verbreitet im Einsatz. Obwohl man sie heute nurnoch vereinzelnd schreibt, findet sich ein spezielles Problem in fast jedem Projekt in dem JSP Custom Tags eingesetzt werden.
Da in Produktion der eingesetzte Web Container die benutzten Tags poolen wird, muss man beim Schreiben von JSP Custom Tags den Lebenszyklus (lifecycle) berücksichtige. Das Tagpooling ist von der Spezifikation erlaubt und sogar empfohlen, verursacht aber Probleme wenn man daran nicht denkt. Speichert man große Objekte in Tags, verursacht man ein Memory Leak welches den Server abstürzen lässt (oder es passiert nichts schlimmes, für den Fall daß der Pool oder das Objekt klein genug ist). In der Entwicklungsumgebung fällt dies auch oft nicht auf.

Der Verursacher sieht meist so aus wie dieser Codeschnipsel:

1public class MyTag extends TagSupport {
2  public Object leak;
3  public int doStartTag(){
4    leak = new BigObject();
5  }
6}
7

Erzeugt wird das Problem dann durch diesen Lebenszyklus:

  1. Klasse laden
  2. Instanz erzeugen
  3. setPageContext() aufrufen
  4. Setter aufrufen
  5. doStartTag aufrufen
  6. In Abhängigkeit von Typ und Rückgabewerten andere Methoden aufrufen
  7. doEndTag() aufrufen
  8. Die Instanz in den Pool legen

Wenn nun der gleiche Tag wieder benutzt wird darf der Container bei Schritt 3 beginnen. Wenn nun der Tagpool auf 10 Objekte eingestellt ist und der gleiche Tag durch 10 simultane Anfragen erzeugt wird, landen 10 Instanzen im Pool. Folgen dann aber nur sporadisch Anfragen, dümpeln 10 Instanzen mit einer Referenz auf das große Objekt im Pool. Und schon haben wir unser Memory Leak.

Man kann dies aber ganz einfach vermeiden indem man „transiente“ Variablen am Ende auf null setze und sie in setPageContext() oder doStartTag() neu befüllt. Am Rande sei hier angemerkt, daß der Konstruktor eines Tags nur einmal gerufen werden könnte, obwohl der gleiche Tag auf hunderten von Seiten verwendet wird. Wie viele Instanzen erzeugt, und damit wie viele Konstruktoren aufgerufen, werden hängt von den Einstellungen des Containers, des Pools und der Serverlast ab.

1public class MyTag extends TagSupport {
2  public Object noLeak;
3 
4  public void setPageContext(PageContext pc){
5    noLeak = new BigObject();
6  }
7 
8  public int doStartTag(){
9  }
10 
11  public void doEndTag(){
12    noLeak = null;
13  }
14}
15

Weitere und bessere Alternativen wären diese Objekte so lokal wie möglich zu machen. Der Tag selbst sollte nur seine gesetzten Attribute kennen.
Ausser dem bisher beschriebenen Memoryleak entsteht noch ein weiteres Problem. Nehmen wir mal an ein Objekt wird nur gesetzt wenn ein bestimmtes Attribut einen bestimmten Wert hat. Ist dies der Fall, wird das Objekt aber nicht wieder entfernt, so findet man das Objekt bei der nächsten Benutzung des Tags wieder, obwohl die Bedingung auf das Attribut nicht mehr zutrifft.

Beitrag teilen

Gefällt mir

0

//

Weitere Artikel in diesem Themenbereich

Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.

//

Gemeinsam bessere Projekte umsetzen

Wir helfen Deinem Unternehmen

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.