RAM freimachen mit KOmprimiertem in-memory-swap

Status
Nicht offen für weitere Antworten.

Javahnsinn

Aktives Mitglied
:D Für alle Java-Freaks, :D


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(); }
 }
}
 

nekton

Aktives Mitglied
Hallo! HAt mich ein wenig muehe gekostet um durch den "gui code" durchzublicken.
hier noch eine variante fuer die "konsolen liebhaber" unter uns ;)
konkreter output ist manchmal garnicht so verkehrt ;)

Code:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

class SimpleSwap
{
  
  public static void main(String args[]) throws Exception
  {
    HeavyObject ho = new HeavyObject();
    
    System.out.println("--- anfang ---");
    testSwap(ho);

    System.out.println("--- ende! ---");
  }
  
  public static void testSwap(HeavyObject ho) throws Exception
  {
    System.out.println("\n\r--- Erzeuge und teste Objekt  ---");
    ho.testOutPut();
    
    System.out.println("\n\r--- Starte Kompression  ---");

    SimpleSwap swap = new SimpleSwap();
    swap.setObject(ho);
    swap.compress();
    swap.decompress();
    
    System.out.println("\n\r--- Wandle Objekt um und teste erneut ---");

    Object o = swap.getObject();
    ho = (HeavyObject) o;
    ho.testOutPut();
  }

  /** beginn der eigentlichen klasse**/
  
  private GZIPOutputStream gzo;
  private ObjectOutputStream oos;
  
  private ObjectInputStream ois;
  private GZIPInputStream gzi;
  
  private ByteArrayInputStream bai;
  private ByteArrayOutputStream bao;

  private Object obj = null;
  
  public SimpleSwap()
  {
  }
  
  public boolean compress(Object inObj) throws IOException
  {
      this.setObject(inObj);
      return this.compress();
  }
  
  public boolean compress() throws IOException
  {
    if(this.obj == null)
    {
      return false;
    }

    // schreibe einmal unkomprimiert um die normale groeße 
    // ermitteln zu koennen
    bao = new ByteArrayOutputStream();
    oos = new ObjectOutputStream(bao);

    oos.writeObject(this.obj);
    oos.close();

    System.out.println("ByteArray vor Comp.: "+ bao.toByteArray().length + " Bytes");
    
    // schreibe komprimiert (also de ritneressantere teil)  
    bao = new ByteArrayOutputStream();
    gzo = new GZIPOutputStream(bao);
    oos = new ObjectOutputStream(gzo);
    
    
    oos.writeObject(this.obj);
    oos.close();

    //clean-up
    this.obj = null;
    System.gc();
    
    // output
    System.out.println("ByteArray nach Comp.: "+ bao.toByteArray().length + " Bytes");

    return true;
  }
  
  public void decompress() throws IOException, ClassNotFoundException
  {
    bai = new ByteArrayInputStream(bao.toByteArray());
    gzi = new GZIPInputStream(bai);
    ois = new ObjectInputStream(gzi);
    
    System.out.println("ByteArray vor Decomp.: "+ bao.toByteArray().length + " Bytes");
    
    obj = ois.readObject();
    ois.close();
    
    // Zum Vergleich: Größe des unkomprimierten Objekts
    bao = new ByteArrayOutputStream();
    oos = new ObjectOutputStream(bao);
    
    oos.writeObject(this.obj);
    oos.close();
    
    // output
    System.out.println("ByteArray nach Decomp.: "+ bao.toByteArray().length + " Bytes");

    //clean-up
    ois = null;
    gzi = null;
    bai = null;
    System.gc();
    
   
  }
  
  public void setObject(Object inObj)
  {
    this.obj = inObj;
  }
  
  public Object getObject()
  {
    return this.obj;
  }
  
}

Code:
public class HeavyObject implements java.io.Serializable
{
  private StringBuffer heavyBuffer = new StringBuffer();
  private String s ;
  private String input;
  
  // erzeuge einfach ganz viele daten damit man was zum komprimieren hat
  public HeavyObject()
  {
    int rounds = 9999;

    this.input = String.valueOf(System.currentTimeMillis());

    for(int i = 0; i<= rounds; i++)
    {  
      heavyBuffer.append(String.valueOf(System.currentTimeMillis()));
    }
    
    s = heavyBuffer.toString();
  }
  
  // um zu testen ob das objekt nach dem dekomprimierung auch wieder heile und
  // funktionsfaehig heraus kommt.
  public void testOutPut()
  {
    System.out.println(this.input);
  }
  
}
 
G

Guest

Gast
Interessant.
Es hängt wohl damit zusammen, dass beim Serialisieren/Deserialisieren, die internen Buffer
diverser Komponenten (DokumentModel von JTextPane, Component-Array der Container etc.)
"entmistet" werden. Ausserdem werden die beim Erstellen der Komponenten allozierten,
temporären Objekte aus dem Speicher gehauen.

Sachen gibt's, das gibt's nicht :wink:
 

Angel

Aktives Mitglied
das is echt sehr interessant, das prob is nur, ich blick da leider überhaupt nicht durch um das benutzen zu können :bahnhof:
 

nekton

Aktives Mitglied
Angel hat gesagt.:
das is echt sehr interessant, das prob is nur, ich blick da leider überhaupt nicht durch um das benutzen zu können :bahnhof:

ist im endeffekt recht einfach. ein objekt wird zu einem array aus bytes. dieses array aus bytes wird dann komprimiert. das heisst dass z.b. ueberfluessige null bytes rausfliegen jedoch zur rekonstruktion vermerkt werden. so geschieht es auch mit diversen anderen teilen des arrays. was am ende herauskommt, ist ein geschrumpftes byte-array.

das ganze funktioniert auch rueckwaerts, so dass aus den rohen bytes wieder objekt erzeugt werden.


Code:
(java code als Object )   ->  [object output stream] -> (java code als byte[]) -> [gzip output stream] -> (zip file als byte[])
 

meez

Top Contributor
Es ist einfach zu bedenken, dass dadurch mehr Rechenleistung gebraucht wird...
Und die ist in einem Handy auch nicht wirklich im Ueberfluss vorhanden...
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Foreign Memory API / Memory-Mapped File Allgemeine Java-Themen 0
C Durch klicken von Button in GUI wird leeres Fenster geöffnet und nicht mein Spiel "Memory" Allgemeine Java-Themen 13
E Java Shared Memory? Allgemeine Java-Themen 6
B Java Sound Memory Overload Allgemeine Java-Themen 0
P Memory Editing mit JNA, tutorial? Allgemeine Java-Themen 3
Q Memory-Leak in BlockingQueue Allgemeine Java-Themen 3
E Zweidimensionales Array Integer[10 000][10 000] -> out of memory? Allgemeine Java-Themen 4
X Bild im Memory zwischen speichern Allgemeine Java-Themen 11
T Java Memory Puzzle Allgemeine Java-Themen 6
H jni memory problem Allgemeine Java-Themen 8
S Memory Leak!!! Allgemeine Java-Themen 7
dayaftereh JVM Memory Usage Allgemeine Java-Themen 5
Z Schwankung "Total Memory"? Allgemeine Java-Themen 8
L Methode "Neues Spiel" für Memory Allgemeine Java-Themen 2
L Brauche Hilfe bei Memory Programmierung Allgemeine Java-Themen 2
H Tomcat VM out of memory Allgemeine Java-Themen 7
M File im memory erzeugen Allgemeine Java-Themen 5
F Frage zu Memory Leak, Garbage Collection und Profiler-Tools Allgemeine Java-Themen 6
P Java Memory Leaks Allgemeine Java-Themen 12
J Out Of Memory - Speicher vergrößern? Allgemeine Java-Themen 2
C ArrayList Out of Memory Allgemeine Java-Themen 28
P out of memory -> heap wächst und wächst Allgemeine Java-Themen 7

Ähnliche Java Themen

Neue Themen


Oben