申请说明:
基于递归的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%)
答案 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()
。
感谢所有相关人员的时间和耐心,我希望这对其他人有用。