为什么javaw.exe占用的内存持续增加,一直不释放

寻妖孽 发布于 2016/07/16 11:49
阅读 2K+
收藏 0

用SWING做的软件,功能就是从网上下载一些图片,用jtable一个row显示已经下载的图片的缩略图和图片名字。发现每显示一个图片,资源管理器里JAVAW.EXE的使用内存就增加,不到1K的图片内存会增加300K左右。用jconsole做监测,堆内存释放很正常,GC回收也及时,显示几K张图片也不会内存泄漏,而且内存增加到60M左右的时候会增加的慢一些,但是还是会持续增加,最高到100M。

eclipse中的设置-Xmx32m -Xms32m -Xmn24m -Xss128k -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeratio=10

到底是什么地方消耗内存,而且还不释放?

加载中
0
Mr_K
Mr_K
使用JVM看下  是那个地方一直在吃内存··
0
寻妖孽
寻妖孽
只有old generration 在每次显示一张图片时会增加个10K内存,其他的都能正常释放
0
扁-哥
扁-哥

1.估计是使用Jtable渲染 TableCellRenderer  图片出问题了,或者显示图片的方式不对.Swing 只需要一个定义一个渲染器实例,然后重复使用就行.

2.看看哪一个类占用的内存比较大.是不是 swing/AWT的类

寻妖孽
寻妖孽
用MAT分析了,发现是toolkit占用old gen一直不释放,代码中使用了JLabel setIcon(imageicon)显示图片,如果在JTable中显示的过多jlabel,就会OOM,但是目前找不到解决的办法
0
寻妖孽
寻妖孽

JLabel jl=new JLabel();
ImageIcon icon=new ImageIcon(imagePath);//应该是这里的问题
jl.setIcon(icon);//应该是这里的问题
Object[] obj={jl,imageName};
tableModel.addRow(obj);


jl=null;
icon=null;
obj=null;
Runtime.getRuntime().gc(); //没什么作用


Jtable渲染 TableCellRenderer  能出什么问题???


@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
    if(column==0)
    {
         JLabel jl=(JLabel)value;
        return jl;
    }
    //other code....
}

0
扁-哥
扁-哥

你的Table DefaultTreeCellRenderer 图片渲染器定义的应该有问题.,因为默认的渲染器就是继承Jlable的,就不要继续new Jlabel,直接设置setIcon();就行. 给个TableCellRenderer  代码你参考下把

1.创建table:

TableColumnModel columnModel = table.getColumnModel();
        StatusTableCellRenderer statusTableCellRenderer = new StatusTableCellRenderer();

        BasicTableCellRenderer columnRenderer = new BasicTableCellRenderer(colsAlignment);

        for (int i = 0; i < table.getColumnCount(); i++) {
            columnModel.getColumn(i).setCellRenderer(columnRenderer);
        }
        columnModel.getColumn(0).setCellRenderer(statusTableCellRenderer);//设置地0个的渲染
        tablePanel.add(tableScrollPanel, BorderLayout.CENTER);

2. BasicTableCellRenderer

package com.swing.table;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;

import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;

public class BasicTableCellRenderer extends DefaultTableCellRenderer {

	private static final long serialVersionUID = 582988421026137695L;
	protected String colsAlignment;

	protected String hperlinkText;
	protected String[] hperlinkIngoreTexts;
	protected Color evenBackground = new Color(244, 244, 244);
	protected Color focusBackground = new Color(176, 199, 233);

	public BasicTableCellRenderer(String colsAlignment) {
		this.colsAlignment = colsAlignment;
		Font font = UIManager.getFont("Table.font");
		setFont(font);
	}

	@Override
	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
			int row, int column) {
		if (row % 2 == 0) {

			setBackground(evenBackground);
		} else {

			setBackground(Color.WHITE);
		}
		if (hasFocus) {
			setBackground(focusBackground);
		}

		if (getCellHorizontalAlignmentByIndex(column) == -1) {
			setHorizontalAlignment(SwingConstants.LEFT);
		} else if (getCellHorizontalAlignmentByIndex(column) == 0) {
			setHorizontalAlignment(SwingConstants.CENTER);
		} else {
			setHorizontalAlignment(SwingConstants.RIGHT);
		}
		super.getTableCellRendererComponent(table, value, isSelected, false, row, column);

		return this;
	}

	protected int getCellHorizontalAlignmentByIndex(int index) {
		if (colsAlignment != null) {
			String[] colStr = colsAlignment.split(";");
			if (colStr.length > index) {
				return Integer.valueOf(colStr[index]);
			} else {
				return 0;
			}
		} else {
			return 0;
		}
	}
}




3.StatusTableCellRenderer

package com.swing.table;

import java.util.Hashtable;

import javax.swing.ImageIcon;
import javax.swing.SwingConstants;

import com.swing.SwingToolkit;
import com.ui.MR;


public class StatusTableCellRenderer extends BasicTableCellRenderer {

    private static final long serialVersionUID = -7165029031183872117L;
    private Hashtable<String, ImageIcon> icons = new Hashtable<String, ImageIcon>();

    /*
     * 200030119=images/table_column_green.png
     * 200030121=images/table_column_red.png
     * 200030123=images/table_column_yellow.png
     */

    public StatusTableCellRenderer() {
        super(null);
        ImageIcon greenIcon = SwingToolkit.createImageIcon(MR.TABLEHEADER_200030119_IMAGE);
        ImageIcon redIcon = SwingToolkit.createImageIcon(MR.TABLEHEADER_200030121_IMAGE);
        ImageIcon yellowIcon = SwingToolkit.createImageIcon(MR.TABLEHEADER_200030123_IMAGE);
        icons.put("0", redIcon);
        icons.put("1", greenIcon);
        icons.put("2", yellowIcon);
        setHorizontalAlignment(SwingConstants.CENTER);
    }

    public void setValue(Object value) {
        
        if (value instanceof String) {
            setIcon(icons.get(value + ""));
        } else {
            super.setIcon(icons.get(value + ""));
        }
    };
}

0
扁-哥
扁-哥
JLabel jl=new JLabel();
ImageIcon icon=new ImageIcon(imagePath);//应该是这里的问题
jl.setIcon(icon);//应该是这里的问题
Object[] obj={jl,imageName};

tableModel.addRow(obj);

这个 地方不对 ,table设置图片 不是添加Jlable,而是使用渲染器来getTableCellRendererComponent 里面 setIcon,你要代码的话,我可以给你一个完整的代码,Swing我们都封装好了的,留下联系方式就行

0
扁-哥
扁-哥

g
这个是Swing做的,下面是个 table.你的这个是 treetable,swing里面的 cell样式,都是通过渲染器的方式来渲染的,不要往里面添加组建,添加组建也要使用 继承:DefaultTableCellRenderer 在这个实现

getTableCellRendererComponent里面添加组建:和

实现TableCellEditor来响应事件



0
寻妖孽
寻妖孽

修改渲染器的代码

public void setValue(Object value) 
{
	String path=(String) value;
	ImageIcon icon = ScalrImage.getScalrImage(path);
	setIcon(icon);
	System.out.println("add icon--"+path);
}


 虽然javaw.exe内存还是会一直增加,但old gen 算是很稳定了,增长的很慢,不像之前用JLable很快就内存泄漏,另外程序暂停时,如果滚动条往上移动查看图片时,还是会执行setValue(Object value)这个方法?难道重新渲染



返回顶部
顶部