作为我的代码的一部分,我需要为具有70k顶点和700k边缘的图形计算一些中心度量。为此,我使用了数组和哈希映射数据结构。不幸的是,我在程序中间耗尽了内存。处理这种情况的最佳JVM热点参数是什么?这是我得到的例外:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.createEntry(Unknown Source)
at java.util.HashMap.addEntry(Unknown Source)
at java.util.HashMap.put(Unknown Source)
所以我用-Xmx6g更改堆大小但是这个参数没有解决问题。我仍然有堆空间相同的问题。
在我的程序中,我想为每个节点计算一些度量,遗憾的是JVM保留所有节点的信息,并尝试按每个节点计算它。我想知道有没有办法以一种从内存中删除不需要的信息的方式更改JVM?例如,在计算70000个节点的1000个节点的度量后,我的代码崩溃了。无论如何在计算后从内存中删除与此1000个节点相关的信息?内存可以这种方式分配给其他节点。这与垃圾收集器有关吗? 这是我的代码(使用JUNG库)
public class FindMostCentralNodes {
private DirectedSparseGraph<Customer, Transaction> network = new DirectedSparseGraph<Customer, Transaction>();
static String dbName="SNfinal";
private int numberofNodes=0;
public static void main(String[] args) throws NumberFormatException, SQLException {
FindMostCentralNodes f=new FindMostCentralNodes();
int counter=1;
DirectedSparseGraph<Customer, Transaction> tsn=f.getTSN();
DistanceCentralityScorer<Customer,Transaction> scorer=new DistanceCentralityScorer<Customer,Transaction>(tsn,false,true,true);// un-weighted
Collection<Customer> subscribers=tsn.getVertices();
for(Customer node:subscribers){
String sql="update Node set dist_centrality='"+scorer.getVertexScore(node)+"' where subscriber='"+node.getName()+"'";
DatabaseManager.executeUpdate(sql,dbName);
System.out.println("Update node centrality measures successfully!: "+counter++);
node=null;
}
}
public DirectedSparseGraph<Customer,Transaction> getTSN() throws NumberFormatException, SQLException{
network= new DirectedSparseGraph<Customer,Transaction>();
String count="select count(*) as counter from Node";
ResultSet rscount=DatabaseManager.executeQuery(count, dbName);
if(rscount.next()) {
numberofNodes=rscount.getInt("counter");
}
Customer [] subscribers=new Customer[numberofNodes];
String sql="select * from Node";
ResultSet rs=DatabaseManager.executeQuery(sql, dbName);
while(rs.next()){
Customer sub=new Customer();
sub.setName(rs.getString("subscriber"));
network.addVertex(sub);
subscribers[rs.getInt("nodeID")-1]=sub;
sub=null;
}
String sql2="select * from TSN";
ResultSet rs2=DatabaseManager.executeQuery(sql2, dbName);
while(rs2.next()){
Transaction transaction=new Transaction(Double.parseDouble(rs2.getString("weight")));
network.addEdge( transaction, subscribers[rs2.getInt("callerNID")-1], subscribers[rs2.getInt("calleeNID")-1] );
transaction=null;
}
//garbage
rscount=null;
rs=null;
rs2=null;
subscribers=null;
return network;
}
}
答案 0 :(得分:1)
垃圾收集器将删除程序中的实时变量无法再访问的任何对象。它会在放弃并抛出OutOfMemoryError
之前删除任何此类对象。如果您认为在内存中保留了太多对象,那么第一个操作过程就是放弃您不需要的任何对象,以便它们不再可访问。由于您尚未向我们展示任何代码,因此我们无法建议您进行任何具体更改。
如果修剪不必要的对象,但仍然没有足够的内存,则可以研究使用更紧凑的方法来存储数据。关键技术是使用堆外存储;这比简单地使用对象更有用,但如果正确完成,则在空间和CPU方面可以更有效。参见:
答案 1 :(得分:0)
答案 2 :(得分:0)
我通过创建一个每次处理500个节点的整个算法的方法来解决问题。每次运行此方法后,GC现在可以删除整个变量,所以我的问题就解决了。