Как сохранить профиль памяти в Java?
====================================

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

Итак, вот что я сделал, я добавил точку останова в начало моей программы и запустил ее, затем я запустил visualVM и настроил ее профиль памяти (я также делал то же самое в netbeans, просто для сравнения результатов, и они тот же самый). Моя проблема в том, что я не знаю, как их читать, я получил высшую область, просто говоря`char[]` и я не вижу никакого кода или чего-либо еще (что имеет смысл, потому что visualvm подключается к jvm и не может видеть мой источник, но netbeans также не показывает мне источник, как при профилировании процессора).

По сути, я хочу знать, какая переменная (и, как мы надеемся, более подробная информация, например, в каком методе) используется вся память, поэтому я могу сосредоточиться на работе там. Есть ли простой способ сделать это? Я сейчас использую eclipse и java для разработки (и установил visualVM и netbeans специально для профилирования, но готов установить все, что, по вашему мнению, выполнит эту работу).

РЕДАКТИРОВАТЬ: В идеале, я ищу что-то, что будет брать все мои объекты и сортировать их по размеру (чтобы я мог видеть, какой из них утомляет память). В настоящее время он возвращает общую информацию, такую как string [] или int [], но я хочу знать, на какой объект он ссылается, чтобы я мог работать над тем, чтобы оптимизировать его размер.

**Strings are problematic**

В основном на Java,`String` ссылки (вещи, которые используют`char[]` за кулисами) будет доминировать большинствоbusiness память приложений мудрая. Как они создаются, определяет, сколько памяти они используют в JVM.

Просто потому, что они так важны для большинства бизнес-приложений, как тип данных, и они также являются одними из наиболее требовательных к памяти. Это не просто вещь Java,`String` Типы данных занимают много памяти практически на каждом языке и в библиотеке времени выполнения, потому что, по крайней мере, это просто массивы из 1 байта на символ или, в худшем случае (Unicode), это массивы из нескольких байтов на символ.

Однажды при профилировании использования ЦП в веб-приложении, которое также имело зависимость JDBC от Oracle, я обнаружил, что`StringBuffer.append()` доминирует циклы ЦП на много порядков по сравнению с другими вызовами методов**combined**намного меньше любого другого отдельного вызова метода. Драйвер JDBC сделал много-много`String` манипулирование, вид компромисса использования`PreparedStatements` За все.

**What you are concerned about you can't control, not directly anyway**

Вам следует сосредоточиться на том, что находится под вашим контролем, что гарантирует, что вы не держите ссылки дольше, чем нужно, и что вы не дублируете вещи без необходимости. Процедуры сборки мусора в Java высоко оптимизированы, и если вы узнаете, как работают их алгоритмы, вы можете убедиться, что ваша программа работает оптимальным образом, чтобы эти алгоритмы работали.

**Java Heap Memory isn't like manually managed memory in other languages, those rules don't apply**

Что считаетсяmemory leaks в других языках это не то же самое / первопричина, как в Java с ее системой сбора мусора.

Скорее всего, в памяти Java не используется один единственный uber-объект, который протекает (свисающая ссылка в других средах).

Это, скорее всего, много меньших выделений из-за`StringBuffer`/`StringBuilder` объекты не имеют соответствующего размера в первых мгновениях, а затем автоматически увеличивают`char[]` массивы для хранения последующих`append()` звонки.

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

**EXAMPLE:** сборщик мусора может решить, что есть кандидаты, но, поскольку он считает, что еще достаточно памяти, что может потребоваться слишком много времени, чтобы избавиться от них в этот момент времени, и он будет ждать, пока не уменьшится нагрузка на память выше.

Сборщик мусора действительно хорош сейчас, но это не волшебство, если вы делаете дегенеративные вещи, это приведет к тому, что он не будет работать оптимально. В Интернете много документации о настройках сборщика мусора для всех версий JVM.

Эти не имеющие ссылки объекты, возможно, просто не достигли того времени, когда сборщик мусора считает, что они необходимы для их удаления из памяти, или могут существовать ссылки на них, удерживаемые каким-либо другим объектом (`List` ) например, вы не понимаете, что указывает на этот объект. Это то, что чаще всего называютleak в Java, которая является ссылкой утечки более конкретно.

**EXAMPLE:** Если вы знаете, что вам нужно построить 4K`String` используя`StringBuilder` создать его с`new StringBuilder(4096);` не по умолчанию, который равен 32 и сразу же начнет создавать мусор, который может многократно представлять то, что, по вашему мнению, должно соответствовать размеру объекта.

Вы можете узнать, сколько объектов какого типа созданы в VisualVM, и вы узнаете, что вам нужно знать. Не будет одного большого проблескового маячка, указывающего на один экземпляр одного класса, который говорит: «Это большой потребитель памяти!», То есть, если только один экземпляр`char[]` что вы читаете какой-то массивный файл, и это тоже невозможно, потому что многие другие классы используют`char[]` внутри; и тогда ты уже знал это.

**I don't see any mention of `OutOfMemoryError`**

Вероятно, у вас нет проблем в вашем коде, система сборки мусора может просто не оказаться под достаточным давлением, чтобы взломать и освободить объекты, которые выthink это должно быть уборка. Какие**you think** проблема, вероятно, нет, если только ваша программа не`OutOfMemoryError`, Это не C, C ++, Objective-C или любой другой язык / среда выполнения, предназначенная для ручного управления памятью. Вы не можете решить, что находится в памяти или нет на том уровне детализации, который, как вы ожидаете, вы сможете.



**JVisualVM** В папке bin, когда ваш сервер приложений (например, запущен), вы можете запустить visualvm и подключить его к вашему локальному хосту, который обеспечит вам выделение памяти и позволит выполнить дамп кучи

[![enter image description here](/imgs/JquYY.png)](/imgs/JquYY.png)

Для более подробных шагов о том, как включить:
<http://sysdotoutdotprint.com/technologies/java/6>



[JProfiler](http://www.ej-technologies.com/products/jprofiler/overview.html), вы можете перейти к кучке и активировать вид самых больших объектов. ы увидите объекты, которые сохраняют большую часть памяти. & Quot; нераспределенной & Quot; Память - это память, которая будет освобождена сборщиком мусора, если вы удалите объект.

Затем вы можете открыть узлы объекта, чтобы увидеть справочное дерево сохраненных объектов. от скриншот самого большого объекта:

![enter image description here](/imgs/Gn5wh.png)

Отказ от ответственности: моя компания разрабатывает JProfiler



мент, как[Eclipse MAT](https://www.eclipse.org/mat/) это позволяет вам анализировать их. Здесь очень много[учебные пособия](http://scn.sap.com/people/krum.tsvetkov/blog/2007/07/02/finding-memory-leaks-with-sap-memory-analyzer) имеется в наличии. Это обеспечивает вид на[дерево доминатор](https://help.eclipse.org/indigo/index.jsp?topic=/org.eclipse.mat.ui.help/concepts/dominatortree.html) чтобы дать представление об отношениях между объектами в куче. Специально для того, что вы упомянули, «путь к корням GC» Функция MAT подскажет вам, где находятся ссылки на большинство объектов char [], String [] и int []. JVisualVM также может быть полезен при выявлении утечек и распределений, особенно с использованием моментальных снимков со следами стека выделения. Есть немало[прохождение процесса](https://rejeev.blogspot.com/2009/04/analyzing-memory-leak-in-java.html) получить снимки и сравнить их, чтобы найти точку распределения.