Hallo,
in der folgenden einfachen Methode eines Java-Agenten möchte ich die Dokumente einer Collection in ein TreeMap speichern und zurückgeben. Der Schlüssel für den späteren Zugriff auf Dokumente soll die eMail-Adresse der Person darstellen:
private TreeMap<String, Document> getLNcontacts (String notesServer, String notesDB)
{
TreeMap<String, Document> mPersons = new TreeMap<String, Document>();
try {
Database db = getSession().getDatabase(notesServer, notesDB, false);
DocumentCollection dc = db.search("SELECT Type = \"Person\"");
Document currDoc = dc.getLastDocument();
while (currDoc != null)
{
if (!currDoc.isDeleted() && currDoc.isValid()) {
String key = currDoc.getItemValueString("InternetAddress").toLowerCase();
(*) mPersons.put(key, currDoc);
}
currDoc = dc.getPrevDocument();
}
} catch (Exception e) {
e.printStackTrace(pwLog);
}
return mPersons;
}
Die Collection "dc" enthält ca. 37 Tausend Dokumente. Wenn ich den Agenten testweise laufen lasse, stürzt der Designer nach einigen Tausend Dokumenten komplett ab und erzeugt ein Eclipse-Coredump. Die Absturzstelle (Dokument bei dem es passiert) ist jedesmal unterschiedlich. Kommentiere ich die mit (*) markierte Zeile aus, läuft das Programm durch (tut aber natürlich weiter nichts, da mir die Daten fehlen). Schreibe ich in den TreeMap ein zuvor erzeugtes Dummy-Dokument, läuft die Methode auch durch. Es ist eindeutig das Problem des Zugriffs auf das sich aktuell im Zugfiff befindene Dokument (hier: currDoc).
Fällt hier jemadem ein Programmierfehler auf?
Danke für eure Unterstützung.
Andreas
Hallo,
vielen Dank für eure Antworten. Ich habe 2 folgende Änderungen eingeführt:
1. Jedes Dokument wird nach dem "Verwenden" gleich freigegeben (recycle()).
2. von jedem Objekt hole ich mir nicht den Verweis auf's "Document", sondern die NotesID (um später darauf zugreifen zu können), da nach dem recycle ist der jeveilige Verweis nicht mehr gültig.
private TreeMap<String, String> getLNcontacts (String notesServer, String notesDB)
{
TreeMap<String, String> mPersonId = new TreeMap<String, String>();
try {
Database db = getSession().getDatabase(notesServer, notesDB, false);
DocumentCollection dc = db.search("SELECT Type = \"Person\"");
writeLog("DB-select liefert: " + dc.getCount() + " dokumente");
Document tmpdoc;
Document doc = dc.getFirstDocument();
int i = 1;
while (doc != null) {
if (!doc.isDeleted() && doc.isValid()) {
Vector itVal = doc.getItemValue("InternetAddress");
if (itVal != null && !itVal.isEmpty()) {
if (itVal.get(0).toString().length() > 5 ) {
String key = itVal.get(0).toString().toLowerCase();
if (mPersonId.get(key) == null)
mPersonId.put(key, doc.getNoteID());
}
}
}
if (i%1000 == 0) {
writeLog("... und wieder ein Tausend: " + i%1000);
i++;
}
// dieses komische Konstrukt wird von IBM empfohlen
tmpdoc = dc.getNextDocument();
doc.recycle();
doc = tmpdoc;
}
// recycle überall...
dc.recycle();
db.recycle();
} catch (Exception e) {
e.printStackTrace(pwLog);
}
return mPersonId;
}
Nun läuft das Programm durch. Ist leider aber sehr langsam. recycle() scheint sehr zeitintensiv zu sein.
Noch einmal vielen Dank für eure Hilfe.
Andreas