Как я могу обнаружить/избежать автоупаковки в Java?

Я работаю над программой, которая постоянно работает с гигабайтами данных, в основном с примитивами и строками. Мне нужно избегать преобразования примитивов в объекты с помощью автоупаковки, поскольку это увеличивает размер кучи и время сборки мусора.

В настоящее время я вношу изменения и запускаю код в VisualVM и вижу, что у меня есть миллионы дополнительных целых или коротких чисел или объектов. Затем я просматриваю код в отладчике в своих библиотеках и классах JDK, чтобы найти, где происходит упаковка. Есть ли инструменты, чтобы помочь с этим?

Я использую Intellij в качестве своей IDE. В Intellij вы можете использовать проверку, чтобы найти автоупаковку в своем собственном коде, но, похоже, она не распространяется на библиотечный код. Для этого выберите в меню:

Analyzye >> Запустить проверку по имени...

Затем введите «авто» в командной строке. Для выбора должна появиться проверка автобокса.

Однако на данный момент я практически полностью удалил автоматическое упаковывание из своего кода. Что мне нужно, так это иметь возможность узнать, когда я передаю примитив в библиотечный метод, является ли код библиотеки автоматически упаковывающим примитив в любой момент.


person L. Blanc    schedule 19.03.2016    source источник
comment
При работе с большими объемами данных, когда автоупаковка становится проблемой, Java может оказаться неподходящим языком для вашего приложения. Рассмотрите возможность использования C или C++. В качестве альтернативы вы можете написать программу на c, которая обрабатывает ваши данные, а затем отображает результаты в вашем Java-приложении.   -  person Mario Dekena    schedule 20.03.2016
comment
Вы пытались найти ошибки?   -  person Sasi Kathimanda    schedule 20.03.2016
comment
Я нашел этот связанный вопрос, который содержит несколько полезных предложений. stackoverflow.com/questions/15818875/   -  person L. Blanc    schedule 20.03.2016
comment
Я должен согласиться с @MarioDekena - не похоже, что java - правильный инструмент для ваших нужд. В зависимости от вашего источника данных и формата вам следует рассмотреть C++ или javascript. Возможно, даже взглянуть на Go.   -  person Software Engineer    schedule 20.03.2016
comment
Что-то, что я видел, что приводит к созданию многих объектов Integer, делает с ними математику. Integer sum = 0; for (int value : values) sum += value; является допустимым кодом, но создаст дополнительный целочисленный объект для каждого члена values.   -  person VGR    schedule 20.03.2016
comment
преобразуется в объекты путем автоупаковки, так как это увеличивает размер кучи и время сборки мусора. ... возможно, вы реагируете на проблему, которой у вас нет. Если вы профилировали свой код и не можете продемонстрировать проблемы с производительностью или памятью, которые могут быть связаны с чрезмерным созданием объектов, то даже если вы непреднамеренно упаковываете примитивы здесь и там, чистое влияние на ваш код будет незначительным. Я с уважением предлагаю вам сообщать о результатах вашего профилирования, прежде чем вы начнете масштабную переработку своего кода.   -  person scottb    schedule 20.03.2016
comment
@scottb Эм, да. Это проблема, которая у меня есть. Спасибо за совет.   -  person L. Blanc    schedule 21.03.2016


Ответы (3)


Вы должны просмотреть свой код на наличие ссылок на Integer, Double и т.д. Это легко сделать с помощью Eclipse или IntelliJ. Возможно, вы храните много данных в Java, построенных в Картах, Коллекциях и т. Д., С оболочками примитивного типа, которые автоматически упаковываются из-за дженериков?

Хороший способ избавиться от этого — использовать GNU Trove вместо Java, встроенных в структуры данных: http://trove4j.sourceforge.net/html/overview.html. In предоставляет карты и коллекции, в которых используются примитивные типы вместо универсальных, и сокращает использование памяти.

Другой причиной создания множества экземпляров объекта может быть использование интерфейса InvocationHandler. Эта вещь создает массив объектов для параметров в методах каждый раз, когда вызывается метод. Прокси-объекты часто используют это. Возможно, у вас есть сторонние библиотеки или собственный код, который делает это?

Наконец, используйте профилировщик, который может отображать экземпляры объектов иерархически. Я думаю, что VisualVM делает это, не уверен.

Вам не нужно прибегать к С++, как это предлагают некоторые. Вы можете проектировать вокруг него.

person Sason Ohanian    schedule 20.03.2016
comment
Спасибо. Я использую библиотеку fastuti fastutil.di.unimi.it, похожую на Trove. Мне придется изучить InvocationHandler. - person L. Blanc; 20.03.2016
comment
Есть лучшие варианты, чем Trove: java-performance.info/ - person leventov; 07.07.2016

Должна быть возможность написать простой javaagent, который добавляет ведение журнала для вызовов valueOf (Integer.valueOf). Все, что вам нужно для этой задачи, — это библиотека для работы с байтовым кодом, такая как Javassist.

person Sami Korhonen    schedule 20.03.2016
comment
Это так весь бокс выполняется? Я предположил, что если вы передадите int i методу foo(Integer i), упаковка будет обработана непосредственно компилятором - person L. Blanc; 20.03.2016
comment
Afaik это всегда делается с использованием valueOf. Посмотрим, смогу ли я найти какие-нибудь доказательства с этим крошечным мобильным экраном :-) - person Sami Korhonen; 20.03.2016
comment
stackoverflow.com/ вопросы/408661/ - person Sami Korhonen; 20.03.2016

Предполагая, что у вас есть исходный код используемых вами библиотек, как насчет использования структурного поиска и замены? Используйте кнопку Copy existing template... в диалоговом окне Структурный поиск и замена и выберите boxed expressions. Это найдет все места, где выражения (не явно) заключены в рамку.

Выполните поиск в области Project and Libraries, чтобы искать везде, или создайте пользовательскую область, например, с таким шаблоном, как lib:omg.a.package..*, для поиска только в этом пакете.

person Bas Leijdekkers    schedule 20.03.2016