Во-первых: Mockito использует CGLIB для создания макетов, а PowerMock использует Javassist для некоторых других вещей, таких как удаление конечных маркеров, Powermock также загружает классы в новый ClassLoader. CGLIB известен тем, что поедает постоянное поколение (просто погуглите CGLIB PermGen чтобы найти соответствующие результаты по этому вопросу).
Это не прямой ответ, поскольку он зависит от деталей вашего проекта:
Как вы указали, есть статический вспомогательный класс, я не знаю, содержит ли также статические переменные с макетами, я не знаю деталей вашего кода, так что это чистое предположение, и другие читатели, которые действительно знают лучше, могут меня исправить .
Это может быть загрузчик ClassLoader (и, по крайней мере, некоторые из его дочерних элементов), который загрузил этот статический класс, может поддерживаться в тестах - это может быть из-за статики (которая живет в области классов< /em>) или из-за какой-то ссылки где-то - это означает, что если ClassLoader все еще жив (т.е. не собирается мусор), его загруженные классы не отбрасываются, т.е.< /em> классы, включая сгенерированные, все еще находятся в PermGen.
Эти классы также могут быть огромными по размеру, если у вас есть много этих классов для загрузки, это может иметь значение для более высоких значений PermGen, тем более что Powermock необходимо перезагружать классы в новом загрузчике классов для каждого теста.
Опять же, я не знаю деталей вашего проекта, поэтому я просто предполагаю, но ваша проблема с постоянной генерацией может быть вызвана либо пунктом 1, либо пунктом 2, либо даже обоими.
В любом случае, вообще говоря, я бы сказал да: наличие статического класса, который может возвращать статический имитированный объект, здесь выглядит как плохая практика, как это обычно бывает в производственном коде. Если он плохо обработан, это может привести к утечке ClassLoader (это неприятно!).
На практике я видел сотни тестов (только с Mockito) без изменения параметров памяти и без выгрузки прокси-серверов CGLIB, и я не использую статические вещи, кроме тех, что из Mockito API.
Если вы используете JVM Sun/Oracle, вы можете попробовать следующие варианты, чтобы отслеживать происходящее:
-XX:+TraceClassLoading
и -XX:+TraceClassUnloading
или -verbose:class
Надеюсь, это поможет.
Выходит за рамки этого вопроса:
Лично мне все равно не нравится использовать Powermock, я использую его только в крайних случаях, например, для тестирования немодифицируемого устаревшего кода. Powermock слишком навязчив, имхо, он должен создавать для каждого теста новый загрузчик классов для выполнения своих действий (изменение байт-кода), вам нужно сильно аннотировать тестовые классы, чтобы иметь возможность издеваться... По моему мнению, для обычной разработки все эти небольшие неудобства перевешивают преимущества возможности имитировать финалы. Даже Йохан, автор Powermock, однажды сказал мне, что вместо этого он рекомендует Mockito и держит Powermock для какой-то конкретной цели.
Не поймите меня неправильно: Powermock — это фантастическая технология, которая действительно помогает, когда вам приходится иметь дело с (плохо) разработанным унаследованным кодом, который вы не можете изменить. Но не для повседневной разработки, особенно если практикуешь TDD.
person
Brice
schedule
27.07.2012