System.gc() ?

Vielen Dank für all eure Antworten!

ich Troll hatte den Fehler doch beim Import und der war sogar ganz offensichtlich :eek: schäm

jetzt beschäftigt mich nur noch Frage 3 für ein anderes Project.

In einem anderen Prog will ich die Daten einer SQL-Tabelle in einer JTable mit JScrollPane anzeigen. Bei großen Tabellen habe ich dann auch wieder dieses Speicherproblem. Welche möglichkeit gibt es hier?

ich poste jetzt an dieser Stelle keinen code, weil ganz offensichtlich ist, dass ich keine 100000 Datensätze in eine JTable speichern kann ohne Heap-Overflow. Die Frage ist nur welche alternativen hab ich.
Am liebsten wäre mir eine lösung, die keine scrollbaren ResultSets verwendet, weil mein Prog mit verschiedenen DBMSn arbeiten soll, auch mit solchen, die keine scrollbaren ResultSets unterstützen.

Danke für eure Ideen! :)
 
Unter JTable und Paging wirst Du bei Google fündig:

ein Beispiel als Basis für eine eigene Implementierung..

Quelle: http://examples.oreilly.com/jswing2/code/ch16/PagingModel.java

Java:
// PagingModel.java
// A larger table model that performs "paging" of its data.  This model
// reports a small number of rows (like 100 or so) as a "page" of data.  You
// can switch pages to view all of the rows as needed using the pageDown()
// and pageUp() methods.  Presumably, access to the other pages of data is
// dictated by other GUI elements such as up/down buttons, or maybe a text
// field that allows you to enter the page number you want to display.
//
import javax.swing.table.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class PagingModel extends AbstractTableModel {

  protected int pageSize;
  protected int pageOffset;
  protected Record[] data;

  public PagingModel() {
    this(10000, 100);
  }

  public PagingModel(int numRows, int size) {
    data = new Record[numRows];
    pageSize = size;
    
    // Fill our table with random data (from the Record() constructor).
    for (int i=0; i < data.length; i++) {
      data[i] = new Record();
    }
  }

  // Return values appropriate for the visible table part.
  public int getRowCount() { return Math.min(pageSize, data.length); }
  public int getColumnCount() { return Record.getColumnCount(); }

  // Work only on the visible part of the table.
  public Object getValueAt(int row, int col) {
    int realRow = row + (pageOffset * pageSize);
    return data[realRow].getValueAt(col);
  }

  public String getColumnName(int col) {
    return Record.getColumnName(col);
  }

  // Use this method to figure out which page you are on.
  public int getPageOffset() { return pageOffset; }

  public int getPageCount() { 
    return (int)Math.ceil((double)data.length / pageSize);
  }

  // Use this method if you want to know how big the real table is . . . we
  // could also write "getRealValueAt()" if needed.
  public int getRealRowCount() {
    return data.length;
  }

  public int getPageSize() { return pageSize; }
  public void setPageSize(int s) { 
    if (s == pageSize) { return; }
    int oldPageSize = pageSize;
    pageSize = s;
    pageOffset = (oldPageSize * pageOffset) / pageSize;
    fireTableDataChanged();
/*
    if (pageSize < oldPageSize) {
      fireTableRowsDeleted(pageSize, oldPageSize - 1);
    }
    else {
      fireTableRowsInserted(oldPageSize, pageSize - 1);
    }
*/
  }

  // Update the page offset and fire a data changed (all rows).
  public void pageDown() {
    if (pageOffset < getPageCount() - 1) {
      pageOffset++;
      fireTableDataChanged();
    }
  }

  // Update the page offset and fire a data changed (all rows).
  public void pageUp() {
    if (pageOffset > 0) {
      pageOffset--;
      fireTableDataChanged();
    }
  }

  // We provide our own version of a scrollpane that includes
  // the page up and page down buttons by default.
  public static JScrollPane createPagingScrollPaneForTable(JTable jt) {
    JScrollPane jsp = new JScrollPane(jt);
    TableModel tmodel = jt.getModel();

    // Don't choke if this is called on a regular table . . .
    if (! (tmodel instanceof PagingModel)) {
      return jsp;
    }

    // Okay, go ahead and build the real scrollpane
    final PagingModel model = (PagingModel)tmodel;
    final JButton upButton = new JButton(new ArrowIcon(ArrowIcon.UP));
    upButton.setEnabled(false);  // starts off at 0, so can't go up
    final JButton downButton = new JButton(new ArrowIcon(ArrowIcon.DOWN));
    if (model.getPageCount() <= 1) {
      downButton.setEnabled(false);  // One page...can't scroll down
    }

    upButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        model.pageUp();

        // If we hit the top of the data, disable the up button.
        if (model.getPageOffset() == 0) {
          upButton.setEnabled(false);
        }
        downButton.setEnabled(true);
      }
    } );

    downButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        model.pageDown();

        // If we hit the bottom of the data, disable the down button.
        if (model.getPageOffset() == (model.getPageCount() - 1)) {
          downButton.setEnabled(false);
        }
        upButton.setEnabled(true);
      }
    } );

    // Turn on the scrollbars; otherwise we won't get our corners.
    jsp.setVerticalScrollBarPolicy
        (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    jsp.setHorizontalScrollBarPolicy
        (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);

    // Add in the corners (page up/down).
    jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
    jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);

    return jsp;
  }
}
 
Noch ein Nachtrag. Wenn Du Deinen Selects eine Zeilennummer mit gibst, kannst Du nach einem Seitenwechsel per SQL die Daten leicht nachladen. Dann spielt es keine Rolle, ob Dein ResultSet scrollbar ist.

Beispiel für einen solchen select:

Code:
SELECT emp_id, lname, fname, job_id, 
(SELECT COUNT(*) FROM employee e2 WHERE e2.lname <= e.lname AND e2.job_id = 10) AS rownumber
FROM employee e
WHERE job_id = 10
ORDER BY lname
 
@limago deine Lösung sieht ja nicht schlecht aus. Allerdings benutzt Du parkete von J2EE und ich nutze J2SE. Kann ich die benötigten API für Record irgendiw einzeln laden und in meinem prog verwenden? Oder welche Lösung kannst Du mir sonst empfehlen?
 
Hi,

Es sind keine Pakete von J2EE dabei. Eine Record-Klasse kannst Du leicht selbst schreiben. Sie kapselt den Zugriff auf die Datenbank.

Ich würde stattdessen eher eine Tableklasse schreiben, mit den einzelnen Methoden

int getColumnCount();
String getValue(int column);
String getValue(String columnName);
String getColumnName(int column);
long getRowCount();
boolean moveToRow(long row);

oder meinetwegen auch

String valueAt(long row, int column);

Den SelectString kann man schon bei der Konstruktion mitgeben. Das Paging-Model bedient sich dann aus dieser Klasse ( die am besten Ihrerseits die Zeilen puffert). Die Klasse "ArrowIcon" ist nur zum malen auf die Buttons da.

Habe leider etwas Stress, sonst würde ich mal eine Lösung schreiben. Vielleicht nächste Woche.

Gruß
 
ich hätte auch mal eine Frage zu System.gc()
Diese Methode weist ja den Garbage Collector an sobald wie möglich zu laufen, gibt es denn eine Möglichkeit rauszufinden wann er läuft oder was ich eigentlich brauche herauszufinden wann er fertig ist mit seinem Durchlauf ?
 
Ich verstehe die Frage nicht ganz.

Wenn Du wissen willst, wann der GC läuft kannst Du die VM mit entsprechenden Parametern starten. Dann werden die Läufe in der Konsole protokolliert.

Siehe hier: http://java.sun.com/developer/JDCTechTips/2004/tt0420.html#2
und hier :http://java.sun.com/developer/JDCTechTips/2004/tt0122.html#2

Wenn Du aus Deiner Anwendung heraus wissen willst, ob ein Objekt definitiv gelöscht wurde, schaue in diesen Thread

http://www.tutorials.de/forum/java/273920-call-value-daten-vom-heap-entfernen.html

Oder willst Du nur ganz schnöde wissen, ob er überhaupt gelaufen ist? Dann wäre ein GC-Monitor nicht schlecht. Hier eine Lösung für Java 6:

http://www.java-forum.org/de/viewtopic.php?p=271063

Gruss
 
Hallo,

eine andere Varainte um festzustellen, ob ein GC erfolgte oder nicht wäre es IMHO die benutzen Memory Bereiche zu tracken.

Hmmm also ich denke diese Form des Memory Trackers ist schon ziemlich grob...
Java:
public class GCMonitor implements Runnable {
		Map<GarbageCollectorMXBean, Long> garabageCollectorCollectionCountMap = new WeakHashMap<GarbageCollectorMXBean, Long>();

		@Override
		public void run() {

			initializeGarbageCollectorCounters();

			while (true) {
				for (GarbageCollectorMXBean garbageCollectorMXBean : ManagementFactory
						.getGarbageCollectorMXBeans()) {

					long currentGarbageCollectorCollectionCount = garbageCollectorMXBean
							.getCollectionCount();

					if (currentGarbageCollectorCollectionCount > garabageCollectorCollectionCountMap
							.get(garbageCollectorMXBean)) {
						garabageCollectorCollectionCountMap.put(
								garbageCollectorMXBean,
								currentGarbageCollectorCollectionCount);
						System.out.println("GC was performed by: "
								+ garbageCollectorMXBean.getName());
					}
				}

				try {
					TimeUnit.SECONDS.sleep(1L);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

		private void initializeGarbageCollectorCounters() {
			for (GarbageCollectorMXBean garbageCollectorMXBean : ManagementFactory
					.getGarbageCollectorMXBeans()) {
				garabageCollectorCollectionCountMap.put(garbageCollectorMXBean,
						garbageCollectorMXBean.getCollectionCount());
			}
		}
	}
Leider implementiert das GarbageCollectorMXBean kein NotificationBroadcaster Interface so das man hier keine NotificationListener anhängen kann. Na ja, vielleicht gibts ja noch einen versteckten JVM-Hook worüber man direkt über GC Events informiert wird. Andere JVM's wie etwa BEA's JRockit bieten sowas IMHO über eine proprietäre API an.

Anonsten gefällt mir die Variante mit der Reference Queue doch besser... da wird man wirklich "direkt" nach dem GC Informiert, da die remove Methode an der ReferenceQueue so lange blockiert bis die nächste (Weak\Soft\Phantom) Reference verfügbar ist. (Und das ist sie eben unmittelbar nach dem finalen GC des gewrappedten Objekts)

Gruß Tom
 
Hi,

Es sind keine Pakete von J2EE dabei. Eine Record-Klasse kannst Du leicht selbst schreiben. Sie kapselt den Zugriff auf die Datenbank.

Ich würde stattdessen eher eine Tableklasse schreiben, mit den einzelnen Methoden

int getColumnCount();
String getValue(int column);
String getValue(String columnName);
String getColumnName(int column);
long getRowCount();
boolean moveToRow(long row);

oder meinetwegen auch

String valueAt(long row, int column);

Den SelectString kann man schon bei der Konstruktion mitgeben. Das Paging-Model bedient sich dann aus dieser Klasse ( die am besten Ihrerseits die Zeilen puffert). Die Klasse "ArrowIcon" ist nur zum malen auf die Buttons da.

Habe leider etwas Stress, sonst würde ich mal eine Lösung schreiben. Vielleicht nächste Woche.

Gruß

Danke nochmal für deine Mühe. Bei meiner Lösung habe ich die Tableklasse so implementiert, dass Sie alle Daten in ein Array reinschreibt. Auf diese Art und Weise, kann ich mir zwar sehr viel größere Tabellen anzeigen lassen, als innerhalb einer einzigen ScrollPane aber bei wirklich großen Tabellen hab ich natürlich immernoch das Speicherproblem. Meine Frage ist wie kann ich die Methoden boolean moveToRow(long row); und String valueAt(long row, int column); ohne scrollable Resultsets implementieren?
 
Zurück