Структуры реализованы как типы значения, и классы являются ссылочными типами. Если у Вас будет переменная типа Foo, и Вы храните экземпляр Fubar в нем, он "Втиснет его" в ссылочный тип, таким образом побеждая преимущество использования структуры во-первых.
единственная причина я вижу для использования структуры вместо класса, то, потому что это будет тип значения и не ссылочный тип, но структура не может наследоваться классу. Если у Вас есть структура, наследовали интерфейс, и Вы раздаете интерфейсы, Вы теряете ту природу типа значения структуры. Мог бы также просто сделать его классом, если Вам нужны интерфейсы.
Я думаю, вы правильно диагностировали: у вас никогда не заканчивается куча Java, поэтому JVM не выполняет сборку мусора, а отображаемые буферы не освобождаются. Тот факт, что вы не Нет проблем при запуске GC вручную, кажется, это подтверждает. Вы также можете включить подробное ведение журнала сбора в качестве вторичного подтверждения.
Итак, что вы можете сделать? Что ж, первое, что я попробую, - это сохранить начальный размер кучи JVM небольшим, используя аргумент командной строки -Xms. Это может вызвать проблемы, если ваша программа постоянно выделяет небольшие объемы памяти в куче Java, поскольку она будет запускать сборщик мусора чаще.
Я бы также использовал инструмент pmap (или любой другой его эквивалент в Windows), чтобы изучить карту виртуальной памяти. Возможно, вы фрагментируете кучу C, выделяя буферы переменного размера. В этом случае вы увидите каждую большую виртуальную карту с промежутками между «анонимными» блоками. И решение здесь - выделить блоки постоянного размера, которые больше, чем вам нужно.
Я подозреваю, что ваша проблема связана с использованием прямых байтовых буферов. Их можно размещать вне кучи Java.
Если вы часто вызываете метод и каждый раз выделяете небольшие буферы, ваш шаблон использования, вероятно, не подходит для прямого буфера.
Чтобы изолировать проблему, я бы переключился на (Java ) буфер, выделенный кучей (просто используйте метод allocate
вместо allocateDirect
. Если это решит проблему с памятью, значит, вы нашли виновника. Следующий вопрос будет: прямой байтовый буфер имеет какое-либо преимущество с точки зрения производительности. Если нет (а я предполагаю, что нет), то вам не нужно беспокоиться о том, как его правильно очистить.
Фактически вы столкнулись с известной ошибкой в Java VM . Лучший обходной путь, указанный в отчете об ошибке:
Другие возможные обходные пути включают:
Если вы действительно хотите полагаться на прямые байтовые буферы, я бы предложил объединение на уровне приложения. В зависимости от сложности вашего приложения,
Если у вас заканчивается память кучи, автоматически запускается сборщик мусора. Однако, если у вас заканчивается прямая память, сборщик мусора не запускается (по крайней мере, на JVM Sun), и вы просто получаете OutOfMemoryError, даже если сборщик мусора освободит достаточно памяти. Я обнаружил, что в этой ситуации вам нужно запускать сборщик мусора вручную.
Лучшим решением может быть повторное использование одного и того же ByteBuffer, чтобы вам никогда не приходилось повторно размещать ByteBuffers.