Эквивалент GC.AddMemoryPressure в Java - PullRequest
7 голосов
/ 16 июля 2011

Проект: Java, JNI (C ++), Android.

Я собираюсь управлять временем жизни нативного объекта C ++, создав управляемый класс-обертку, который будет содержать указатель на нативный объект (как длинныйmember) и удалит собственный объект в переопределенном методе finalize ().Подробнее см. в этом вопросе .

Объект C ++ не использует другие типы ресурсов, только память.Объем памяти объекта не очень высок, но он существенно выше, чем у 64-битной длины в Java.Можно ли как-то сказать GC Java, что моя оболочка отвечает не только за длинное значение, но и не стоит создавать миллионы таких объектов перед запуском сборки мусора?В .NET есть метод GC AddMemoryPressure (), предназначенный именно для этой цели.Есть ли эквивалент в Java?

Ответы [ 2 ]

5 голосов
/ 18 августа 2011

После еще одного поиска, я нашел хорошую статью от IBM Research Center.

Вкратце, они рекомендуют использовать кучу Java вместо собственной кучи для собственных объектов. Таким образом, давление памяти на сборщик мусора JVM более реалистично для нативных объектов, на которые ссылаются из кода Java через дескрипторы.

Для этого необходимо переопределить стандартные функции выделения и освобождения кучи C ++: оператор new и оператор delete. В новом операторе, если JVM доступна (JNI_OnLoad уже был вызван), тогда тот вызывает NewByteArray и GetByteArrayElements, который возвращает необходимую выделенную память. Чтобы защитить созданный ByteArray от сбора мусора, необходимо также создать для него NewGlobalRef и сохранить его, например. в том же выделенном блоке памяти. В этом случае нам нужно выделить столько памяти, сколько требуется, плюс память для ссылок. В операторе delete необходимо удалить DeleteGlobalRef и ReleaseByteArrayElements. Если JVM недоступна, вместо нее используются собственные функции malloc и free.

1 голос
/ 14 августа 2011

Я считаю, что собственная память выделяется за пределами размера кучи Java. Это означает, что вам не нужно беспокоиться о том, что ваше выделение памяти отнимает у значения, зарезервированного вами с помощью -Xmx<size>.

При этом вы можете использовать ByteBuffer.allocateDirect () для выделения буфера и GetDirectBufferAddress для доступа к нему из вашего собственного кода. Вы можете контролировать размер кучи прямой памяти, используя -XX:MaxDirectMemorySize=<size>

...