Проблема в этом коде заключается в том, что объект, на который ссылается продукт, никогда не удаляется сборщиком мусора (GC). Я мог бы проверить это, просмотрев объект как живой экземпляр в отладчике Eclipse.Объект никогда не удаляется сборщиком мусора
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;
}
Если я не ошибаюсь, объект указываемого продукт в настоящее время хранится в живых, потому что некоторые ссылки на него (или, может быть ссылкой на члена продукта) также жив. Но я не мог найти такую ссылку (я могу добавить больше кода, если это необходимо).
Моя цель - избавиться от предмета, на который указывает продукт.
EDIT
Следит код ConditionalProbabilityTableOperation.marginalize
:
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;
}
Решение
После @ the8472 предложение использовать профайлер памяти я мог бы идентифицировать объект, на который указывает product
в YourKit моментальный снимок памяти. Удивительно, но после цикла for этот объект исчез! Это означает, что, возможно, отладчик действительно каким-то образом удерживал объект (как это было предложено другими в этом потоке), останавливая GC для его удаления. Это было удивительно для меня, так как я работал до небольшого примера в аналогичном контексте, и отладчик не удерживал объект в этом примере. Я не могу понять, почему это не удержит это время и держится в этом, но в любом случае это похоже на ошибку отладчика. Спасибо всем за вашу поддержку.
Что такое внутренние для ConditionalProbabilityTableOperation.marginalize()? – Wash
Поддерживает ли 'ConditionalProbabilityTableOperation.marginalize' ссылку на' product'? –
Как создается «маргинальный»? Используете ли вы какие-либо ссылки на членство от продукта? –