Java:从无用的对象中清除内存

时间:2016-12-26 15:17:41

标签: java object memory clear

申请说明:
基于递归的Swing应用程序,允许我正在研究的特定数字组的可视化。它使用一个名为Node的类,它有一个递归构造函数,因此它占用大量内存,因为每个Node为自己创建一个节点系列,它存储在Vector中。程序本身只显示由节点本身生成的树形图。 (请记住,我限制了节点的乘法容量)

我的问题:
该程序使用太多的内存。我知道占用记忆的是节点,但我不知道如何摆脱它们。我试过System.gc(),但这对内存管理没有用。 (我使用标准的任务管理器来验证它使用了多少RAM) 我并不真的需要自己的节点,我只需要他们给我BufferedImage所以我可以在程序中使用它,但是他们坚持占用大量的内存。 / p>

为了说明它使用了多少内存,4个限制因子为5的不同节点占用了大约1 GB的RAM。

一般问题:
我真正的问题和大多数人感兴趣的问题是:"我如何摆脱我不再使用的声明对象?"

编辑:班级Node不在我正在使用的班级内,他们只是同一个班级的一部分。

节点类:

package tailingprimes;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;

public class Node {

    public BufferedImage canvas;
    public double angle, radius, arm_size;
    public int x,y,arms,limit;
    public long value;
    public Node parent;
    public Vector<Node> children;
    public Vector<Long> branch;
    public static int side = 600;
    public static double rad_scale = 0.3;
    public static double arm_scale = 0.3;

    public Node(Node nParent, long primeValue, int xPos, int yPos, double dAngle, int iLimit)
    {
        this.canvas = new BufferedImage(side,side,BufferedImage.TYPE_INT_RGB);
        this.value = primeValue;
        this.x = xPos;
        this.y = yPos;
        this.angle = dAngle;
        this.limit = iLimit;
        this.parent = nParent;
        this.children = new Vector<Node>();
        this.branch = TailingPrimePlus.primeBranch(value);
        this.arms = this.branch.size();
        Graphics ctx = this.rootCanvas().getGraphics(); 

        if(nParent == null)
        {
            ctx.setColor(Color.WHITE);
            ctx.fillRect(0, 0, 600, 600);
            this.radius = 10;
            this.arm_size = 150;
        }
        else
        {
            this.radius = rad_scale*parent.radius;
            this.arm_size = arm_scale*parent.arm_size;
            ctx.setColor(Color.GREEN);
            ctx.drawLine(this.x, this.y, this.parent.x, this.parent.y);
            this.arms++;
        }

        int real_radius = (int) Math.round(this.radius);
        ctx.setColor(Color.BLACK);
        ctx.drawOval(this.x-real_radius, this.y-real_radius, 2*real_radius, 2*real_radius);

        if(limit > 0)
        {
            for(int t = 0; t < this.branch.size(); ++t)
            {
                double real_angle = this.angle + (t+1)*2*Math.PI/this.arms;
                double real_distance = this.radius + this.radius*rad_scale + this.arm_size;
                int x_now = this.x + (int) Math.round(real_distance*Math.cos(real_angle));
                int y_now = this.y + (int) Math.round(real_distance*Math.sin(-real_angle));
                Node now = new Node(this,this.branch.get(t),x_now,y_now,real_angle+Math.PI,this.limit-1);
                this.children.add(now);
            }
        }
    }

    public BufferedImage rootCanvas()
    {
        if(parent==null)
        {
            return canvas;
        }
        else
        {
            return parent.rootCanvas();
        }
    }

    public Node getNodeByTreeCode(long treeCode)
    {
        String text = Long.toString(treeCode);
        int val = Integer.parseInt(text.substring(0,1)) - 1;
        if(val >= children.size()){return null;}
        if(text.length() > 1)
        {
            long next_val;
            next_val = Long.parseLong(text.substring(1));
            Node ans = children.get(val).getNodeByTreeCode(next_val);
            return ans;
        }
        else
        {
            return children.get(val);
        }
    }
}


JFrame扩展程序:

package tailingprimes;

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.beans.DefaultPersistenceDelegate;

import javax.swing.*;

public class TailingPrimePlus extends JFrame implements ActionListener{

    public int canvas_width = 600;
    public int canvas_height = 600;
    public static int current_step = 0;
    public static long root = 1;

    public JPanel p1 = new JPanel();
    public JPanel p2 = new JPanel();
    public JPanel p3 = new JPanel();

    public JButton b1 = new JButton("1");
    public JButton b2 = new JButton("3");
    public JButton b3 = new JButton("7");
    public JButton b4 = new JButton("9");
    public JButton bclear = new JButton("Clear");
    public JButton fwd = new JButton(">>");
    public JButton rwd = new JButton("<<");

    public JLabel step_text = new JLabel("Current Step: ");
    public JLabel step_label = new JLabel("0");

    {
        b1.setActionCommand("1");
        b2.setActionCommand("3");
        b3.setActionCommand("7");
        b4.setActionCommand("9");
        bclear.setActionCommand("clear");
        fwd.setActionCommand("fwd");
        rwd.setActionCommand("rwd");
    }

    public JLabel image_holster = new JLabel();

    public TailingPrimePlus()
    {
        setVisible(true);
        setSize(new Dimension(800,800));
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        int xval = (1920-800)/2;
        int yval = (1080-800)/2;
        this.setBounds(xval, yval, 800, 800);
        setLayout(new GridBagLayout());

        GridBagConstraints cons = new GridBagConstraints();

        cons.fill = 1;
        cons.gridy = 0;
        cons.weighty = 200;
        add(p1, cons);
            p1.setLayout(new GridBagLayout());
            JPanel sub_1_1 = new JPanel();
            p1.add(sub_1_1,cons);
                sub_1_1.add(b1);
                sub_1_1.add(b2);
                sub_1_1.add(b3);
                sub_1_1.add(b4);
                b1.addActionListener(this);
                b2.addActionListener(this);
                b3.addActionListener(this);
                b4.addActionListener(this);
            JPanel sub_1_2 = new JPanel();
            cons.gridy = 1;
            p1.add(sub_1_2, cons);
                sub_1_2.add(step_text);
                sub_1_2.add(step_label);

        cons.gridy = 1;
        cons.weighty = 600; 
        add(p2, cons);
            p2.add(image_holster);

        cons.gridy = 2;
        cons.weighty = 200;
        add(p3,cons);
            p3.add(rwd);
            rwd.setEnabled(false);
            rwd.addActionListener(this);
            p3.add(fwd);
            fwd.setEnabled(false);
            fwd.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        Node current = new Node(null,1,300,300,0,0);
        String command = e.getActionCommand();
        if(command.equals("1") || command.equals("3") || command.equals("7") || command.equals("9"))
        {
            long val = Long.parseLong(command);
            root = val;
            current = new Node(null,val,300,300,0,current_step);
            BufferedImage next_canvas = current.canvas;
            image_holster.setIcon(new ImageIcon(next_canvas));
            rwd.setEnabled(true);
            fwd.setEnabled(true);
        }
        else if(command.equals("fwd"))
        {
            current_step++;
            current = new Node(null,root,300,300,0,current_step);
            BufferedImage next_canvas = current.canvas;
            image_holster.setIcon(new ImageIcon(next_canvas));
        }
        else if(command.equals("rwd"))
        {
            current_step--;
            current = new Node(null,root,300,300,0,current_step);
            BufferedImage next_canvas = current.canvas;
            image_holster.setIcon(new ImageIcon(next_canvas));
        }
        current = null;
        step_label.setText(Integer.toString(current_step));
        validate();
    }

    public static HashMap<Long, Long> safeBranchOut(long root, int limit)
    {
        HashMap<Long, Long> tree = new HashMap<Long,Long>();
        long cursor = 0;
        branchOut(root, limit, cursor, tree);
        return tree;
    }

    public static void branchOut(long root, int limit, long cursor, HashMap<Long, Long> tree)
    {
        long current_root = root;
        int current_limit = limit;
        if(cursor < Math.pow(10, limit-1))
        {
            Vector<Long> current_branch = primeBranch(current_root);
            for(int t = 0; t < current_branch.size(); ++t)
            {
                ++cursor;
                current_root = current_branch.get(t);
                tree.put(cursor, current_root);
                cursor *= 10;
                branchOut(current_root, current_limit, cursor, tree);
                cursor /= 10;
            }
        }
    }

    public static boolean isPrime(double num)
    {
        if(num == 1) {return false;}
        else if(num == 2) {return true;}
        else if(num%2 == 0) {return false;}
        else
        {
            for(double t = 3; t <= Math.sqrt(num); t+=2)
            {
                if(num%t==0 && num!=t)
                {
                    return false;
                }
            }
            return true;
        }
    }

    public static Vector<Long> primeBranch(Long root)
    {
        Vector<Long> ans = new Vector<Long>();
        for(int t = 1; t <= 9; ++t)
        {
            String text = root.toString();
            text = t + text;
            long abs = Long.parseLong(text);
            if(isPrime(abs))
            {
                ans.addElement(abs);
            }
        }
        return ans;
    }

    public static void main(String args[])
    {
        new TailingPrimePlus();
    }
}

This is what the tree looks like


更新:

我安装了VisualVM,我发现内存采样器中的字段int[]正在保存所有内存&#34; leak&#34;。如果我不得不猜测,这与我一直在使用的Vectors有关,但我不确定。有谁知道这意味着什么以及如何处理它?<​​/ p>

仔细检查后,在使用VisualVM的测试中,我验证了这一点:

VisualVM:Thread Name: AWT-EventQueue-0 Alocated Bytes: 467.286.672 (90.1%)

2 个答案:

答案 0 :(得分:2)

如果你有一个包含一些无用对象的类,垃圾收集器将不会收集它们,因为它们仍然被引用,但你可以考虑为这些变量分配null

答案 1 :(得分:0)

问题解决了!

我设法解决了我的问题! 在Node构造函数中,我只是替换了session_start(); // Set session variables $_SESSION["TestSession"] = $value; // Get session echo $_SESSION["TestSession"];

this.canvas = new BufferedImage(600,600,BufferedImage.TYPE_INT_RGB)

因为只有第一个节点需要画布(if(nParent == null){this.canvas = new BufferedImage(side,side,BufferedImage.TYPE_INT_RGB);})。

最后,我对内存分配问题错了,结果与节点无关,我只需要意识到我正在创建非常重的空rootCanvas()

感谢所有相关人员的时间和耐心,我希望这对其他人有用。