gpt4 book ai didi

java - 线程结束工作后,JVM不会释放字节数组的内存

转载 作者:行者123 更新时间:2023-12-01 11:43:23 25 4
gpt4 key购买 nike

我在通过 jvm 释放内存时遇到问题。我知道java从run方法退出后会释放线程资源的内存。当其他对象没有引用时,垃圾收集器会删除它们,但有一些异常(exception),例如窗口/框架。为什么在下面的代码中,尽管线程结束了工作,gc 仍然不释放字节数组的内存?我知道 System.gc() 只是 gc 的建议,但我使用它只是为了以防万一,并且为字节数组引用分配 null 是不必要的。
下面的代码只是示例,当服务器向客户端发送文件时,我的客户端-服务器应用程序在类似的情况下遇到了真正的问题。

 private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
int j=0;
for (int i=0;i<5;i++){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
j++;
new Thread(new Runnable(){
public void run(){
byte[] bytes=new byte[1024*1024*100];
try {
Thread.sleep(15000);
} catch (InterruptedException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("exiting "+Thread.currentThread().getName());
bytes=null;
System.gc();
}
}, ""+j).start();

}
System.gc();
}

我离开上面的问题并走向实用。早些时候,曾将整个文件加载到一个字节数组并使用 writeObject() 发送它,但这会导致内存问题。看看这段代码:

                BufferedOutputStream bos = null;                    
byte[] bytes;
int count;
for (int i = 0; i < filesToUpdate.size(); i++) {
if (mapp.get(filesToUpdate.get(i)) == null) {
addNewFile(filesToUpdate.get(i));
}
bos = new BufferedOutputStream(new FileOutputStream(new File(filesToUpdate.get(i))));
long bufferSize = ois.readLong();
ous.writeObject(2);
ous.flush();
bytes =new byte[8192];
while ((count=ois.read(bytes))>0){
bos.write(bytes, 0, count);
}
bos.flush();
bos.close();
ous.writeObject(3);
ous.flush();
}
ois.readObject();
updateRevision(mapp, filesToUpdate);

客户端接收文件。收到最后一个数据包后,读取第一个文件中的方法 block 。这是服务器端:

       int count;           
File file;
FileInputStream fis=null;
byte[] bytes;
for (int i=0;i<filesForPatch.size();i++){
if (pc.getWhat()==0)
path="admin/";
else path="client/";
path+=filesForPatch.get(i);
file=new File(path);
long buffSize=file.length();
ous.writeLong(buffSize);
ous.flush();
ois.readObject();
fis=new FileInputStream(file);
bytes=new byte[8192];
while ((count=fis.read(bytes))>0){
ous.write(bytes, 0, count);
}
ous.flush();
fis.close();
ois.readObject();
}

有什么想法可以解决这个问题吗?

最佳答案

您从 Windows 任务管理器获得的信息意义不大。 JVM 根据许多因素动态调整堆大小,吞吐量是首要考虑的因素。堆大小永远不会完全等于可访问对象分配的实际内存。

如果您想观察垃圾收集的效果,请使用 VisualVM 连接到您的 JVM。为了获得最佳效果,请安装VisualGC插件并打开其选项卡,您将能够实时观察各代大小的变化。垃圾收集将立即反射(reflect)在显示的占用中,并且您还可以注意到堆本身何时调整大小(很少)。

关于java - 线程结束工作后,JVM不会释放字节数组的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29328211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com