Outputstream belegt übermäßig viel Speicher

Abapking

Mitglied
Hallo zusammen,
ich habe mir nun ein Applet gebastelt, dass mir Dateien mittels einer URL-Connection auf einen Server lädt. Um die Dateien letztendlich auf dem Server zu speichern, nutze ich den OutputStream mit der Methode "write". Da ganze funktioniert auch wunderbar, jedoch wird bei jedem Schleifendurchlauf, und somit mit jedem Outputstream.write(...) immer mehr Arbeitsspeicher belegt. Bei einer 60 MB Datei sind das ganze dann sagenhafte 170 MB in meinem RAM.

Hier ein paar Hintergrundinformationen:
- Das Applet liegt auf einem Projektserver und wird mit einer HTML-Seite ausgeführt.
- Ich habe bereits die maximale Speicherausnutzung von der JVM komplett ausgereizt (256MB).
- Es soll mit dem Applet möglich sein, Dateien mit bis zu 1GB Größe auf den Server zu laden.

Ich habe unten das Coding beigefügt. Hat von Euch jemand eine Idee, wieso der Speicherverbrauch so hoch ist. Mache ich da vielleicht was falsch?

Code:
//			create url object
			URL toUrl = new java.net.URL(strPathTo);
//			create url-connection and connect to defined url
			URLConnection toConn = toUrl.openConnection();
//			set doInput and doOutput to TRUE, because we will use the url-
//			connection for input and output data - set also the
//			RequestProperty
			toConn.setDoInput(true);
			toConn.setDoOutput(true);
			toConn.setRequestProperty("Content-Type",
					"multipart/form-data; boundary=" + strBoundary);
//			calculate the total data upload size
			intTotalSize = strMessages[0].getBytes().length
					+ strMessages[1].getBytes().length + intDiskFileSize;
			toConn.setRequestProperty("Content-Length", "" + intTotalSize);
			System.out.println("Multipart-POST: total size of request = "
					+ intTotalSize);
			osDataOutputStream = toConn.getOutputStream();
//			start to write the data
			System.out.println("Multipart-POST: message 1 =\r\n"
					+ strMessages[0]);
			osDataOutputStream.write(strMessages[0].getBytes());
//			set Parameters for Process-Bar
			jprbrProgressBar.setMinimum(0);
			jprbrProgressBar.setMaximum(intTotalSize);
//			start to write the file-data
			System.out.println("Start to write... with msg2... packetsize = " + intPacketSize);
			while ((intOnePacket = fisFileInputStream.read(bytBuffer, 0, intPacketSize)) >= 0) {
//				write data
				osDataOutputStream.write(bytBuffer, 0, intOnePacket);
//				calculate total file size, which was uploaded
				intTotalFileSize += intOnePacket;
//				update process bar
				jprbrProgressBar.setValue(intTotalFileSize);
//				"security"-safe - second save command
				osDataOutputStream.flush();
//				Test to split!
			}
//			last progress-bar update
			jprbrProgressBar.setValue(intTotalSize);
//			set status text (bottom of info-popup)
			jlblFinishing.setText("Completion - Please Wait!");
//			write last message, save (twice) and close stream
			System.out.println("Multipart-POST: message 2 =\r\n"
					+ strMessages[1]);
			osDataOutputStream.write(strMessages[1].getBytes());
			osDataOutputStream.flush();
			System.out.println("Close streams...(flushed after each package)");
			osDataOutputStream.flush();
			strMsgs = new String[] { "The Content Server reports an error. ",
					"Contact your System Administrator.", "", };
			System.out.println("Close outputstream....");
			osDataOutputStream.close();
 
Hallo!

Ich wuerde dir empfehlen die unnoetig vielen Kommentare wegzulassen.
Dinge wie
// set doInput and doOutput to TRUE, because we will use the url-
// connection for input and output data - set also the
// RequestProperty
kann man entweder durch den lesen des Codes bzw. durch einen Blick in die API erkennen. So viele unnoetige Kommentare verwirren nur...
Weiterhin solltest du dir diese ungarische Notation abgewoehnen. Das hat man "frueher" gemacht (gebraucht), als die IDEs noch nicht so "schlau" waren wie heute. Das verwirrt fasst noch mehr als die Kommentare...

Ich vermute mal, dass du einen Fehler bei der Implementierung der upload Logik gemacht hast und a) das Komplette File in den Speicher ziehest und eine Referenz darauf haelst oder b) du irgendwelche Resourcen nicht wieder frei gibst,...

Gruss Tom
 
Hallo Tom,
gut das mit den Kommentaren ist eine andere Sache, aber der Uplouad-Schritt ansich, ist nicht mehr als die abgebildete Funktion. Muss ich den Zugriff auf den OutputStream vieleicht anders handhaben oder gibt es eine Funktion die die Ressourcen, sprich den Speicher wieder freigibt?
Gruß Simon
 
Hallo!

Schau mal hier:
Unser Servlet:
Code:
/**
 * 
 */
package de.tutorials.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Tom
 * 
 */
public class UploadServlet extends HttpServlet {
    protected void doPut(
            HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        InputStream inputStream = request.getInputStream();
        String fileName = request.getParameter("fileName");
        FileOutputStream fileOutputStream = new FileOutputStream("c:/tmp/"
                + fileName);
        byte[] buffer = new byte[16834];
        int len = 0;

        while ((len = inputStream.read(buffer)) > 0) {
            fileOutputStream.write(buffer, 0, len);
            fileOutputStream.flush();
        }
        fileOutputStream.close();
    }
}

und hier unser Uploader Client:
Code:
package de.tutorials;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class Uploader {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        File file = new File("d:/data.zip");
        URLConnection urlConnection = new URL(
                "http://localhost:48080/de.tutorials.test/uploadServlet?fileName="
                        + file.getName()).openConnection();
        urlConnection.setDoOutput(true);
        ((HttpURLConnection) urlConnection).setRequestMethod("PUT");

        OutputStream outputStream = urlConnection.getOutputStream();
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] buffer = new byte[16384];
        int bytesRead = 0;
        while ((bytesRead = fileInputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, bytesRead);
            outputStream.flush();
        }
        fileInputStream.close();
        outputStream.close();
        System.out.println(((HttpURLConnection) urlConnection)
                .getResponseCode());
    }
}

Gruss Tom
 
Zurück