В Java это нормальная практика, когда все освобождается - это способ, который можно отлаживать. Для некоторых проектов, требующих обфускации, у них может быть сборка релиза, но я никогда не видел этого за 12 лет разработки Java.
Такие вещи, как утверждения и сообщения отладки, обычно отключаются во время выполнения для производственного экземпляра, но при необходимости могут быть включены в любое время (даже динамически).
ИМХО, рекомендуется использовать одну и ту же сборку в каждой среде, а не только один и тот же источник, но одни и те же файлы JAR. Это дает вам максимальную вероятность того, что, если он работает в тестовом режиме, он будет работать в производственном процессе, а если у вас возникнут проблемы в производственном процессе, вы можете повторно воспроизвести его в тестовом режиме.
Поскольку так много Java-кода написано таким образом, JIT очень хорош в оптимизации мертвого кода, который никогда не вызывается. Настолько, что IMHO, большинство микро-«эталонов», где Java out выполняет C ++, это когда эталон ничего не делает и JIT лучше обнаруживает это. ИМХО, C ++ предполагает, что разработчик достаточно умен, чтобы не писать код, который ничего не делает.