关于java内存回收的疑问

understandok 2016-08-03 09:48:29
最近给公司写了一个小型数据处理服务器,具备以下功能:
接收多个设备TCP连接
对于每个连接,独自接收客户端发送来的字节数组数据进行处理(存储到数据库)

以下是具体实现(采用多线程):
首先启动一个Swing窗体,点击启动按钮开启服务器(开启服务端口监听,while(true)循环中执行ServerSocket.accept())

定义一个数据处理线程类DataSocketThread(后面简写dst)(包含ServerSocket.accept()得到的Socket)

每当ServerSocket.accept()到Socket就开启一个包含此Socket的dst线程

dst线程run方法中也是一个while(flag)的循环中通过Socket的InputStream不停地read,期间通过多种方式(设置read超时、异常处理等方式设置flag=false来结束线程)

项目分为许多个类和包

以上内容大致一看,以下是存在问题:

项目运行在win7 64位 jdk-7u80-windows-i586(32位),运行参数java -Xmx200m -Xms20m com.i5.start.Start

按照运行参数设置,java虚拟机内存不会超过200M,但实际运行会超过200M,不只是一点点,目前测试最高到了600多M,也没报内存溢出异常。难道我设置的不正确吗?但之前用一个小测试程序测试时达到指定内存会报内存溢出异常,到了这里为什么就不报了?(测试程序多线程也测试过)

小测试程序为
import java.util.ArrayList;

public class TestCrash implements Runnable {
public static void main(String[] args) throws InterruptedException {

TestCrash tc = new TestCrash();
new Thread(tc).start();

ArrayList<TestCrash> arr = new ArrayList<>();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
arr.add(new TestCrash());
if (i % 200 == 0) {
System.out.println(i);
}
}
}

@Override
public void run() {
ArrayList<TestCrash> arr = new ArrayList<>();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
arr.add(new TestCrash());
if (i % 200 == 0) {
System.out.println(i);
}
}
}
}


同时在运行这个小程序的时候,如果不设置内存运行参数,那么占用内存会很快增长,这时我的服务器程序占用内存会逐渐减小,直到几M,这说明服务器程序的GC开始工作,而且程序本身也并没有不释放资源。

问:
1、在不设置java虚拟机运行内存的情况下,程序占内存会越来愈大,最后在win7下停止工作(可能是操作系统强制java虚拟机停止)
2、设置了运行内存,但为什么总会超,既不及时回收又不报内存溢出异常,最终还是会被操作系统终止


请问怎样解决??(表达能力有限,童鞋们凑合看哈~~~)
...全文
159 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
understandok 2016-08-04
  • 打赏
  • 举报
回复
引用 1 楼 qq_35209952 的回复:
先说个题外话 Xmx200m -Xms20m 建议设置成一样的,可以减少碎片开销 目前测试最高到了600多M,也没报内存溢出异常. 你看Windows的那个不是很准的,而且Xmx也只是堆的大小 按照你的意思感觉是怀疑内存泄漏?试过jconsole吗,监视内存看一下吧. 配合jmap查看引用 不设置虚拟机内存也是有一个默认大小的. 直到几M,这说明服务器程序的GC开始工作,而且程序本身也并没有不释放资源。 这时候你的程序还没有工作吧 .而且似乎也难以确定有没有被写入swap ? 真的没有抛出outofmemory吗..表示怀疑
对于内存管理这块,我也是刚刚进行了解,一些概念还不太熟悉,目前只知道gc、-Xmx、-Xms这几个概念。 我先研究下jconsole、jmap 提出这些问题的前提:程序确已运行,程序每10s接收(Socket)并处理(处理并存储到数据库),运行一天了,才积攒了这么多内存。 又有几个问题: 1、outofmemory是不是只能被抛出,不能被catch处理吧?如果抛出是在哪里被抛出,main方法还是我的单个线程的run方法? 2、是不是需要设置单线程的内存大小 3、目前又发现一点,由于网络的原因客户端经常断线,是不是每个dst对象没有及时被释放??我能够确保每个含Socket的dst线程的run方法已经结束(run结束之前用log4j记录日志,同时打印到控制台),run方法结束之前已经将所有打开的资源(Socket、数据conn)关闭,通过命令行运行netstat -ano|findstr PID查看连接也正常。 目前只能通过每天一运行TestCrash小程序来挤压服务器程序的内存占用来防止程序死掉。(挤压内存期间程序运行正常,数据能够正常存储到数据库)
逗泥丸的平方 2016-08-04
  • 打赏
  • 举报
回复
outofmemory 应该是哪里申请空间,而此时通过gc也无法获得空间时抛出的 事发点应该是不可预期的. 说线程的话.... 线程占用的内存..这个有点记不清了, -Xmx这些只是堆内存,线程的内存是独立的,好像也可以配置,不过参数想不起来了..(懒得百度了,哈哈) 这部分一般不会很大吧... 说起来.. 不知道有没有尝试过控制你的线程池的 大小?
逗泥丸的平方 2016-08-03
  • 打赏
  • 举报
回复
先说个题外话 Xmx200m -Xms20m 建议设置成一样的,可以减少碎片开销 目前测试最高到了600多M,也没报内存溢出异常. 你看Windows的那个不是很准的,而且Xmx也只是堆的大小 按照你的意思感觉是怀疑内存泄漏?试过jconsole吗,监视内存看一下吧. 配合jmap查看引用 不设置虚拟机内存也是有一个默认大小的. 直到几M,这说明服务器程序的GC开始工作,而且程序本身也并没有不释放资源。 这时候你的程序还没有工作吧 .而且似乎也难以确定有没有被写入swap ? 真的没有抛出outofmemory吗..表示怀疑

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧