我正在编写客户端 - 服务器程序。客户端位于同一WLAN上的另一台计算机上。我遇到的问题是客户端的这个例外:java.lang.OutOfMemoryError: Java heap space
。
问题是如果我也使用服务器计算机作为客户端(同一台机器上的Server-Client),它不会抛出此异常。但是,每次我从另一台计算机运行客户端以下载文档时,它都会抛出异常。
请帮助我们轻松解决这个问题。我使用Eclipse。
以下是我的客户端类:
public void run() {
try {
servsock = new ServerSocket(13330);
while (true) {
System.out.println("Waiting on question server...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
// receive file
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = sock.getInputStream();
String LocalLocation = "C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject+"\\"+filename;
File LocalFile = new File(LocalLocation);
File file = new File("C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject);
if (!file.exists()) {
new File("C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject).mkdirs();
System.out.println(file+ " now exists.");
}
File outputfile = new File("C:\\NewEvalve\\LocalUploadedFiles\\"+clasx+"\\"+subject+"\\"+filename);
fos = new FileOutputStream(outputfile);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File " + FILE_TO_RECEIVED
+ " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null) fos.close();
if (bos != null) bos.close();
if (sock != null) sock.close();
} }
} catch (IOException e) {
e.printStackTrace();
}
......这是我上传文件的服务器类:
public void uploadIt(InetAddress retur2, String fileLocation2){
try{
File myFile = new File (fileLocation2);
sock = new Socket(retur2, 13330);
System.out.println("Connection on "+sock.getRemoteSocketAddress());
os = sock.getOutputStream();
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os.write(mybytearray,0,mybytearray.length);
fis.close();
bis.close();
os.flush();
os.close();
System.out.println("Sent " + fileLocation2 + "(" + mybytearray.length + " bytes)");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (bis != null)bis.close();
if (os != null) os.close();
if (sock!=null) sock.close();
System.out.println("Completed Upload");
} catch (IOException e) {
e.printStackTrace();
}}
}
答案 0 :(得分:1)
如果您正在阅读文本文件,那么您应该使用 BufferedReader& BufferedWriter ,而不是一次读取整个文件,比如
File file = new File("your file");
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
BufferedReader br = new BufferedReader(new FileReader("your file"));
while ((currentLine = br.readLine()) != null) {
bw.write(currentLine);
}
bw.close();
br.close();
如果您正在读取二进制文件,则建议使用 BufferedInputStream&的BufferedOutputStream 即可。您无法使用BufferedReader 读取二进制数据,因为它将二进制数据转换为字符串格式&您的文件将损坏或损坏。
您的文件中可能没有行终止符。在这种情况下,读者继续读取文件,直到堆内存中有空间。这就是为什么你得到 OutOfMemory 错误。
编辑:
要对音频文件执行读/写操作, Java Standard Edition - Sound 中有一个扩展名。您可以使用 javax.sound.sampled。* 包中的类。
音频文件示例:
File fileIn = new File("your file");
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(fileIn);
// do something
File fileOut = new File("new file");
if (AudioSystem.isFileTypeSupported(AudioFileFormat.Type.WAVE, audioInputStream)) {
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, fileOut);
}
要详细了解声音包,请查看此Java Sound API
要使用视频文件格式,您可以执行以下操作: -
Java getResourceAsStream("your video file")
中有一个返回InputStream对象的方法。您可以使用此流来读取视频文件数据&将它写入另一个文件或任何你想做的事情。
InputStream getResourceAsStream(String name) - Java Doc一些示例代码如下所示: -
try {
InputStream in = this.getClass().getResourceAsStream("your video file");
BufferedInputStream bis = new BufferedInputStream(in);
BufferedOutputStream bus = new BufferedOutputStream(new FileOutputStream(
new File("your new video file")));
byte[] data = new byte[in.available()];
int read = in.read(data);
bus.write(read);
} catch (IOException ex) {
}
答案 1 :(得分:0)
实际上,您只需调整VM将使用的最大内存量即可。只需使用-Xmx<size>
参数进行调整即可。例如,-Xmx512m
将使用最大512 MB的内存。
我还注意到你正在将一个文件作为一大块内容读入内存。我会一块一块地做(如1或2 kb的碎片),以防止巨大的即时记忆需求。
答案 2 :(得分:0)
HotSpot根据计算机上的总物理RAM调整其堆大小。更改主机时,会隐式更改堆限制。看起来,在您的远程计算机上,您拥有较少的RAM,因此您达到了极限。
但是,真正的建议是不要将整个文件加载到内存中;而是以块的形式读取文件并将它们直接写入网络套接字。然后,无论文件大小如何,您都不会遇到此问题。同样的推理也适用于服务器端:不要将整个文件从套接字读入RAM,而是将其直接转储到文件中。
答案 3 :(得分:-1)
尝试提高perm空间,将以下参数添加到vm启动
-XX:PermSize = 256m -XX:MaxPermSize = 256m
还添加 -XX:MaxPermSize = 256m to Tomcat in Eclipse: Server > Open Launch Configuration > Arguments
参考链接在这里:Out of memory