Für alle Java-Freaks,
Hier wird euch ein Verfahren vorgestellt, mit dem Ihr knappen RAM in euren Anwendungen optimal nutzen könnt. OK, ein 512MB-PIV mit 60gig-HD ist kein C64, aber Java soll ja auch auf Handies und dergleichen laufen...
Also: Der Trick ist ein in-Memory-Swap. Was soll das bringen, RAM ist schließlich RAM? Es bringt doch was, wenn man die mit Serialisierung ge"swapp"ten Objekte gleichzeitig gZIPt!! Streams sind einfach was wundervolles.
Kopiert euch einfach den Code der beiden folgenden Klassen mit copy 'n paste als Demo, compiliert das Zeuch und startet es mal.... Ist ein one-shot, also ohne viel Kommentare - dafür kurz und bündig...
MFG, Jürgen
NewJFrame.java
Das Hauptfenster der Demo
NewJDialog.java
Der Dialog, der komprimiert und geswappt wird
Hier wird euch ein Verfahren vorgestellt, mit dem Ihr knappen RAM in euren Anwendungen optimal nutzen könnt. OK, ein 512MB-PIV mit 60gig-HD ist kein C64, aber Java soll ja auch auf Handies und dergleichen laufen...
Also: Der Trick ist ein in-Memory-Swap. Was soll das bringen, RAM ist schließlich RAM? Es bringt doch was, wenn man die mit Serialisierung ge"swapp"ten Objekte gleichzeitig gZIPt!! Streams sind einfach was wundervolles.
Kopiert euch einfach den Code der beiden folgenden Klassen mit copy 'n paste als Demo, compiliert das Zeuch und startet es mal.... Ist ein one-shot, also ohne viel Kommentare - dafür kurz und bündig...
MFG, Jürgen
NewJFrame.java
Das Hauptfenster der Demo
Code:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.zip.*;
import javax.swing.*;
public class NewJFrame extends javax.swing.JFrame {
JButton jButton1;
GZIPOutputStream gzo;
ObjectOutputStream oos;
ObjectInputStream ois;
GZIPInputStream gzi;
ByteArrayInputStream bai;
ByteArrayOutputStream bao;
NewJDialog dialog;
int compSize;
long bytesFreed = 0;
int nClicks = 0;
/** Auto-generated main method */
public static void main(String[] args) {
showGUI();
}
/**
* Auto-generated code - any changes you make will disappear!!!
* This static method creates a new instance of this class and shows
* it inside a new JFrame, (unless it is already a JFrame).
*/
public static void showGUI() {
try {
NewJFrame inst = new NewJFrame();
inst.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
JLabel jLabel1;
public NewJFrame() {
initGUI();
}
/**
* Initializes the GUI.
* Auto-generated code - any changes you make will disappear.
*/
public void initGUI() {
try {
preInitGUI();
jButton1 = new JButton();
jLabel1 = new JLabel();
BorderLayout thisLayout = new BorderLayout();
this.getContentPane().setLayout(thisLayout);
thisLayout.setHgap(0);
thisLayout.setVgap(0);
this.setTitle("DEMO: In-Memory-Swap mit Kompression");
this.setSize(new java.awt.Dimension(375, 268));
jButton1.setText("In-Memory Swap");
jButton1.setLabel("Einen netten Dialog anzeigen...");
jButton1.setHorizontalAlignment(0);
jButton1.setHorizontalTextPosition(0);
jButton1.setVerticalAlignment(3);
jButton1.setVisible(true);
this.getContentPane().add(jButton1, BorderLayout.SOUTH);
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
BorderLayout jLabel1Layout = new BorderLayout();
jLabel1.setLayout(jLabel1Layout);
jLabel1Layout.setHgap(0);
jLabel1Layout.setVgap(0);
jLabel1.setText("...");
jLabel1.setHorizontalAlignment(0);
jLabel1.setVisible(true);
this.getContentPane().add(jLabel1, BorderLayout.CENTER);
postInitGUI();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Add your post-init code in here
*/
public void postInitGUI() {
jLabel1.setText("Ursprünglich sind "+ Runtime.getRuntime().freeMemory()
+ " Bytes frei...");
dialog = new NewJDialog();
}
/**
* Add your pre-init code in here
*/
public void preInitGUI() {
}
/** Auto-generated event handler method */
public void jButton1ActionPerformed(ActionEvent evt) {
nClicks++;
switch (nClicks) {
case 4 : { System.exit(0); }
case 1 : ; // 1. und 2.Buttonklick
case 2 : {
try {
dialog.show(true); // wenn grad' ge"null"t-> Exception!
bytesFreed = 0;
}
catch (NullPointerException isCompressed) {
String freeBytes = jLabel1.getText().split(" ")[0];
bytesFreed = Long.parseLong(freeBytes);
bytesFreed -= Runtime.getRuntime().freeMemory();
jLabel1.setText( // Anzeige, was Sache...
""+ bytesFreed
+ " Bytes vom GC nach in-memory-swap freigegeben");
jButton1.setText("Dialog wiederherstellen aus RAM-swap");
return;
}
try {
setTitle("Kompressions-SWAP (in memory) läuft...");
jLabel1.setText(
""+ Runtime.getRuntime().freeMemory()
+ " Bytes sind frei VOR dem Swap");
// Jetzt kommts: SWAP
bao = new ByteArrayOutputStream();
gzo = new GZIPOutputStream(bao);
oos = new ObjectOutputStream(gzo);
oos.writeObject(dialog);
oos.close();
dialog = null; // Weg mit dem Objekt!
System.gc();
jButton1.setText("Und das Ergebnis?");
setTitle("Der Dialog ist jetzt in-menory komprimiert!");
compSize = bao.toByteArray().length;
}
catch (Exception e) { e.printStackTrace(); }
break;
} // endcase 1-2
case 3 : {
try { // Dekompression
setTitle("Dialog-Dekompression aus RAM-swap läuft...");
bai = new ByteArrayInputStream(bao.toByteArray());
gzi = new GZIPInputStream(bai);
ois = new ObjectInputStream(gzi);
dialog = (NewJDialog) ois.readObject();
ois.close();
// Zum Vergleich: Größe des unkomprimierten Objekts
bao = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bao);
oos.writeObject(dialog);
oos.close();
jLabel1.setText(
"Und unkomprimiert sind's "+ bao.toByteArray().length
+ " Bytes");
dialog.setTitle("After compression to " + compSize + " Bytes!");
ois = null; gzi = null; bai = null;
System.gc();
setTitle("DEMO: In-Memory-Swap mit Kompression");
dialog.show(true);
}
catch (Exception e) { e.printStackTrace(); }
jButton1.setText(
"Coole Demo, was? Klicken Sie hier, um zu beenden!");
} // endcase 3
} // endswitch
} // endhandler
}
NewJDialog.java
Der Dialog, der komprimiert und geswappt wird
Code:
import javax.swing.*;
import java.awt.BorderLayout;
import java.io.*;
public class NewJDialog extends javax.swing.JDialog implements Serializable {
JTextPane jTextPane1;
public NewJDialog() {
initGUI();
}
/**
* Initializes the GUI.
* Auto-generated code - any changes you make will disappear.
*/
public void initGUI() {
try {
preInitGUI();
jTextPane1 = new JTextPane();
BorderLayout thisLayout = new BorderLayout();
this.getContentPane().setLayout(thisLayout);
this.setTitle("Uncompressed Dialog");
this.setModal(true);
this.setSize(new java.awt.Dimension(368, 241));
jTextPane1.setText(
"Nach dem Schließen dieses modalen Dialogfeldes wird das "+
"Obejkt, das diesen Dialog repräsentiert, in einen ByteArrayOutputStream "+
"geGZIPt. Danach wird die Objektreferenz \"genullt\" und der Garbage-"+
"Collector der VM gestartet. Anschließend wird bei einem Klick auf den "+
"Button angezeigt, wieviel Bytes der GC freigeben konnte. Bei einem "+
"weiteren Klick auf den Button wird der Dialog wiederhergestellt "+
"(deserialisiert) und angezeigt. Nach dem Schließen des Dialogs kann "+
"durch einen Klick auf den Button die Demo geschlossen werden.");
jTextPane1.setVisible(true);
this.getContentPane().add(jTextPane1);
postInitGUI();
}
catch (Exception e) { e.printStackTrace(); }
}
/**
* Add your pre-init code in here
*/
public void preInitGUI() { }
/**
* Add your post-init code in here
*/
public void postInitGUI() {}
/** Auto-generated main method */
public static void main(String[] args) {showGUI();}
/**
* Auto-generated code - any changes you make will disappear!!!
* This static method creates a new instance of this class and shows
* it inside a new JFrame, (unless it is already a JFrame).
*/
public static void showGUI() {
try {
NewJDialog inst = new NewJDialog();
inst.setVisible(true);
}
catch (Exception e) { e.printStackTrace(); }
}
}