此代码中的问题是垃圾收集器(GC)永远不会删除 product 引用的对象。我可以通过在Eclipse的调试器中将对象视为活动实例来验证这一点。
RewriteBase /hooks/
如果我没有错, product 指向的对象将保持活跃状态,因为对它的一些引用(或者可能是产品成员的引用)也是活着的。但我找不到这样的参考(如果需要我可以添加更多代码)。
我的目标是摆脱产品指向的对象。
修改
遵循public static List<ConditionalProbabilityTable> sumOut(List<ConditionalProbabilityTable> factorization, List<Variable> varsToSumOut) {
List<ConditionalProbabilityTable> newFactorization = new ArrayList<>(factorization);
for (Variable varToSumOut : varsToSumOut) {
List<ConditionalProbabilityTable> relevantCpts = Inference.getAllCptsContaining(newFactorization, varToSumOut);
ConditionalProbabilityTable product = Inference.multiplyAll(relevantCpts);
ConditionalProbabilityTable marginal = ConditionalProbabilityTableOperation.marginalize(product, varToSumOut);
newFactorization.removeAll(relevantCpts);
newFactorization.add(marginal);
}
return newFactorization;
}
的代码:
ConditionalProbabilityTableOperation.marginalize
解决方案
按照@8472建议使用内存分析器,我可以在YourKit内存快照中识别public static ConditionalProbabilityTable marginalize(ConditionalProbabilityTable cpt, Variable variable) {
ConditionalProbabilityTable marginalCpt = new ConditionalProbabilityTable();
// Determine the scope of the new CPT.
List<Variable> marginalCptLeftVariables = new ArrayList<>();
marginalCptLeftVariables.addAll( cpt.getLeft());
marginalCptLeftVariables.remove(variable);
marginalCpt.addAllToLeft(marginalCptLeftVariables);
List<Variable> marginalCptRightVariables = new ArrayList<>();
marginalCptRightVariables.addAll(cpt.getRight());
marginalCptRightVariables.remove(variable);
marginalCpt.addAllToRight(marginalCptRightVariables);
// Summation loop
int j = 0;
int[] assignments = new int[cpt.getNumberOfVariables()];
int numberOfRowsInMarginal = marginalCpt.getNumberOfRows();
List<Double> marginalValues = new ArrayList<>(Collections.nCopies(numberOfRowsInMarginal, 0.0));
for (int i = 0; i < cpt.getNumberOfRows(); i++) {
marginalValues.set(j, marginalValues.get(j) + cpt.getValue(i));
for (int l = 0; l < cpt.getNumberOfVariables(); l++) {
assignments[l] = assignments[l] + 1;
int lVarCard = cpt.getVariable(l).getCardinality();
if (assignments[l] == lVarCard) {
assignments[l] = 0;
j = j - (lVarCard - 1) * marginalCpt.getStride(cpt.getVariable(l));
} else {
j = j + marginalCpt.getStride(cpt.getVariable(l));
break;
}
}
}
marginalCpt.setValues(marginalValues);
return marginalCpt;
}
指向的对象。令人惊讶的是,在for循环之后,该对象消失了!这意味着可能调试器确实以某种方式持有对象(正如此线程中的其他人所建议的那样),停止GC移除它。这对我来说是令人惊讶的,因为我已经在类似上下文中的一个小例子之前运行,并且调试器在该示例中没有保持该对象。我无法理解为什么它没有占用这个时间并保持在这个时间,但无论如何它似乎是调试器的错误。
谢谢大家的支持。
答案 0 :(得分:0)
使用内存分析器,创建堆转储,查找有问题的对象,检查这些对象的gc根路径。
具体步骤取决于探查器/转储分析器工具。