В этом случае нет «утечки памяти».Утечка памяти определяется как случаи, когда приложение не может восстановить память.В этом случае утечки нет, поскольку все экземпляры XObject
(и XObject[]
) могут быть восстановлены в определенный момент времени.
Снимок профилировщика памяти, полученный из VisualVM, дает следующие наблюдения:
- Все экземпляры
XObject
(и XObject[]
) создаются при вызове метода XPathExpression.evaluate
. XObject
экземпляры восстанавливаются, когда они более недоступны из корня GC,В вашем случае корнями GC являются локальные переменные result
и testResult
, которые являются локальными для стека основного потока.
Исходя из вышеизложенного, я полагаю, что ваше приложение испытываетили может возникнуть истощение памяти, а не утечка памяти.Это верно, когда у вас есть большое количество XObject
/ XObject[]
экземпляров из оценки выражения XPath, которые не были восстановлены сборщиком мусора, потому что
- они все еще доступны изкорень GC,
- или сборщик мусора еще не пришел, чтобы вернуть их.
Единственное решение первого - это сохранить объекты в памяти на время, котороеони необходимы.Похоже, вы не нарушаете это в своем коде, но ваш код, безусловно, можно сделать более эффективным - вы сохраняете результат первого выражения XPath, которое будет использоваться вторым, когда, безусловно, его можно будет выполнять более эффективно.//Product/Test
может использоваться для извлечения Test
узлов, а также для получения родительских значений Product
Идентификаторы узлов показаны в следующем фрагменте (который оценивает только одно выражение XPath вместо двух):
expr = xpath.compile("//Product/Test");
nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++)
{
Node node = nodes.item(i);
System.out.println(node.getParentNode().getAttributes().getNamedItem("id"));
System.out.println(node.getTextContent());
}
System.out.println(nodes.getLength());
Что касается второго наблюдения, вы должны получить журналы GC (используя флаг запуска verbose:gc
JVM).Затем вы можете принять решение изменить размеры молодого поколения, если у вас создано слишком много недолговечных объектов, поскольку существует вероятность того, что достижимые объекты будут перемещены в постоянное поколение, что приведет к вероятности того, что для восстановления объектов потребуется большая коллекция.которые на самом деле недолговечны по своей природе.В идеальном сценарии (с учетом вашего опубликованного кода) цикл сбора данных молодого поколения должен выполняться каждые несколько итераций цикла for, поскольку экземпляры XObject
, которые являются локальными для цикла, должны возвращаться, как только локальные переменные блокавыйти за рамки.