LINUX.ORG.RU

[дикость] delete в Java


0

2

Из года в год читаю здесь о пожирании явой памяти. А почему никто до сих пор не запилил ключевое слово delete в Java, дабы можно было руками чистить память в обход GC? Это устранило бы «жручесть» Java, но оставило все плюшки: не хочешь думать о памяти - не используй delete. Кроме того, т.к. Java - managed, проблемы с delete, присущие C++, легко устраняются. Например, проблема с использованием уже удалённого участка памяти: при первом же обращении к удалённому участку можно выдать исключение с полным описанием проблемы, что, где и почему (вплоть до строки кода).

★★★
Ответ на: комментарий от Sadler

Где аргументация?

Ты только на пальцах понимаешь? Оке. Давай наводками.

Что если на удаленный участок памяти кто-то ссылался?

baverman ★★★
()
Ответ на: комментарий от Legioner

Это вопросы реализации и конкретных алгоритмов. Скорее всего, это решаемые проблемы. Главное - концепция.

Sadler ★★★
() автор топика

Кастую в тред разговоры об арифметике указателей в яве.

segfault ★★★★★
()
Ответ на: комментарий от baverman

> Что если на удаленный участок памяти кто-то ссылался?

Будет на одно исключение больше.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Нет, алгоритмы прежде всего. Есть алгоритмы менеджмента кучи с ручным удалением. Это malloc/free. Поверх этого можно прикрутить сборщик мусора (Boehm GC), но он будет гораздо хуже работать, чем сборщик мусора в Java. Есть алгоритмы эффективной сборки мусора, но delete туда не прикрутить.

А определение разыменования удалённого объекта - вообще не могу себе представить. Только если при вызове delete перебирать ВСЕ ссылки в программе и если они ссылаются на удаляемый объект, занулять их.

Legioner ★★★★★
()
Ответ на: комментарий от Sadler

Будет на одно исключение больше.

Ты идиот? Может я чего-то не понял в твоих объяснениях. Давай по-порядку.

1. Есть область памяти, на нее ссылается объект1 и объект2.

2. Вызывается delete объект1

3. ....

4. При обращении к объект2 кидается исключение.

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

baverman ★★★
()
Ответ на: комментарий от Legioner

> А определение разыменования удалённого объекта - вообще не могу себе представить.

При вызове delete на объект устанавливается флаг «deleted» и данные из него стираются, сам объект продолжает висеть до сборки мусора. При попытке обращения к объекту выбрасывается исключение.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Если ссылка была единственной, GC подчистит.

И как это соотносится с висящими ссылками? Висящая ссылка, это ссылка, которая ссылается на несуществующий в памяти объект.

Если на объект было две ссылки, ты удалил объект при помощи delete, что будет со второй ссылкой? Правильно, она будет просто указывать куда-то в память. Если правильно подшаманить объект, то можно выполнить произвольный код вне JVM.

alpha2
()
Ответ на: комментарий от Sadler

> Как напишешь, так и будет.

Вот именно поэтому и сыпались бы.

thesis ★★★★★
()
Ответ на: комментарий от Sadler

>Очевидное решение - подгружать их с HDD в объект, из которого извлекать и парсить матрицу пикселей.

И про memory mapped buffer ты почитать конечно поленился?

А по поводу delete - так работа gc несколько более сложная и комплексная чем отдача памяти, и ты своим ручным закатыванием солнца настолько перепортишь ему всю обедню что тормоза будут неимоверные.

И да - delete - ничего не ускорит.



r ★★★★★
()
Ответ на: комментарий от alpha2

При вызове delete на объект устанавливается флаг «deleted» и данные из него стираются, сам объект продолжает висеть до сборки мусора. При попытке обращения к объекту выбрасывается исключение.

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

alpha2
()
Ответ на: комментарий от alpha2

> Если на объект было две ссылки, ты удалил объект при помощи delete, что будет со второй ссылкой? Правильно, она будет просто указывать куда-то в память. Если правильно подшаманить объект, то можно выполнить произвольный код вне JVM.

Т.е. других способов реализации нет по определению?

Sadler ★★★
() автор топика
Ответ на: комментарий от r

> И про memory mapped buffer ты почитать конечно поленился?

Это умозрительный эксперимент, как было сказано выше.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

на объект устанавливается флаг «deleted» и данные из него стираются,

Ололо, и как это раньше не догадались так делать? Удивительно. Не находишь?

baverman ★★★
()
Ответ на: комментарий от alpha2

> Ещё не хватало, что-бы в произвольном месте вылетали исключения, из-за того что кто-то удалил объект.

Если это даст более эффективное управление памятью, я бы пошёл на это.

Sadler ★★★
() автор топика

Что мешает писать на православных крестах?! Там есть «delete», более того его использование по назначению настоятельно рекомендовано :D

erfea ★★★★★
()
Ответ на: комментарий от erfea

> Что мешает писать на православных крестах?! Там есть «delete», более того его использование по назначению настоятельно рекомендовано :D

На них и пишу.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

При вызове delete на объект устанавливается флаг «deleted» и данные из него стираются, сам объект продолжает висеть до сборки мусора. При попытке обращения к объекту выбрасывается исключение.

Т.е. при каждом разыменовании указателя мы получаем ещё дополнительную проверку. 1000 и 1 способ сделать медленный язык :)

Ну хорошо. А после сборки мусора как мы определим, что объект удалён? Эта область памяти наверняка будет использоваться для другого объекта. Например может так получиться, что старая ссылка на удалённый объект будет указывать в середину нового объекта. При попытке чего то понять вообще будет бред и полный C++.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Ну хорошо. А после сборки мусора как мы определим, что объект удалён? Эта область памяти наверняка будет использоваться для другого объекта.

Дак ведь, пока хоть одна ссылка жива, объект не будет удалён. Ссылку прибьют - удалится. Суть в том, что объект этот практически ничего не будет весить, данных в нём нет.

Sadler ★★★
() автор топика

если тебе надо чтобы GC запускался чаще, для этого у jvm есть jvmoptions. хотя по-любому если у тебя одномоментно занято объектами памяти на 2 гига, как ты уменьшишь этот объем? фотожоп точно также для обработки больших изображений память жрет, еще никто на фотожоп не жаловался, даже iRAM и SSD для скретч файла покупают

Karapuz ★★★★★
()
Ответ на: комментарий от Karapuz

> сли тебе надо чтобы GC запускался чаще, для этого у jvm есть jvmoptions.

Нет, мне это не нужно. Я тут думаю о принципиальной оптимизации, а не конкретном примере.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

>Это умозрительный эксперимент, как было сказано выше.

Ну хорошо, ты умозрительно про mmapped buffer прочитать поленился?

Суть вопрса в том что умозрительно задача исходно делается неверно, а потом изобретаются delete.

r ★★★★★
()

Короче, ладно, проще попробовать реализовать это дело, а потом посмотреть, быстрее будет или медленнее.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Т.е. мы вызвали delete, но объект не удалился, просто какой то битик по смещению -1 установился, мол deleted. Ну теперь идея стала понятной.

А зачем вообще всё это? Мы получаем несколько лишних инструкций при каждом разыменовании ссылки (очень частая операция), чтобы проверить на удалённость и выбросить исключение.

При этом память реально становится доступной только после garbage collection, и то если больше ссылок не осталось.

И чего ради всё это? Чтобы поймать InvalidPointerException из за того, что ты невовремя удалил объект?

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> При этом память реально становится доступной только после garbage collection

Нет-нет, память становится доступной сразу. Ради этого всё и затевалось.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Очевидное решение - подгружать их с HDD в объект


подгружай в один и тот же объект, не заводи каждый раз новый

Karapuz ★★★★★
()
Ответ на: комментарий от Karapuz

> подгружай в один и тот же объект, не заводи каждый раз новый

Повторюсь в четвёртый раз. Это умозрительный эксперимент, некорректный, корявый код, первое, что пришло в голову. Не думаю, что это единственное возможное применение для ручного удаления участков памяти. Если хотите, придумайте другое, лучше.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Но если память становится доступной сразу, значит в ней будет выделен какой-нибудь объект. И разыменование ссылки на старый объект приведёт к доступу к произовольной части нового объекта. Про что я и говорил перед этим.

Можно конечно несколько байтиков оставлять занятым, для метаинформации, мол здесь был удалённый объект, и выделять новые объекты дальше. Тогда операция new станет очень долгая. Сейчас операция new в джаве очень быстрая. Не нужно искать место, где выделить объект, оно известно сразу. При реализации наподобие сишной кучи придётся искать место, где выделить новый объект, т.е. получим сильное замедление очень часто используемой операции new и фрагментацию памяти до GC.

Я думаю, если бы это можно было сделать без проблем, это бы сделали. Пока я GC с возможностью delete в управляемых безопасных языках не видел.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Не нужно искать место, где выделить объект, оно известно сразу. При реализации наподобие сишной кучи придётся искать место, где выделить новый объект, т.е. получим сильное замедление очень часто используемой операции new и фрагментацию памяти до GC.

А вот это уже веский аргумент, принимаю. Для реализации такой штуки нужны совсем другие алгоритмы GC.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Не думаю, что это единственное возможное применение для ручного удаления участков памяти. Если хотите, придумайте другое, лучше.


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

Karapuz ★★★★★
()
Ответ на: комментарий от Sadler

>При вызове delete на объект устанавливается флаг «deleted» и данные из него стираются, сам объект продолжает висеть до сборки мусора. При попытке обращения к объекту выбрасывается исключение.

Угу.
Во-первых, тогда при каждом обращении к объекту рантайм будет проверять, существует ли этот объект. Особенно хорошо обращаться в произвольное место в массиве.
Во-вторых, GC надо будет усложнять. Поскольку теперь объект может существовать и иметь ссылки на другие объекты, но эти ссылки нужно будет считать уничтоженными.
В-третьих, практика показывает, что «не хочешь — не надо» не работает. Разве что если программист работает над всеми своими проектами один, что... хм... ну ты понел.
В-четвертых, Java сызмальства затачивалась под эффективный GC, а не под ручное управление памятью.

Вам выше по треду подсказывают: если хотите экономить память, зачем плодите тучу объектов? А если бы писали на чистых сях, то каждый раз отдельно malloc бы вызывали для всех изображений своих, которые после одного использования выкидываются?

Потом, если не нравится, что жрет много памяти, поставьте ограничение -Xmx<сколько вам надо>.

proud_anon ★★★★★
()
Ответ на: комментарий от proud_anon

> Вам выше по треду подсказывают: если хотите экономить память, зачем плодите тучу объектов? А если бы писали на чистых сях, то каждый раз отдельно malloc бы вызывали для всех изображений своих, которые после одного использования выкидываются?

Нет. Это умозрительный эксперимент, некорректный, корявый код, первое, что пришло в голову. Не думаю, что это единственное возможное применение для ручного удаления участков памяти. Если хотите, придумайте другое, лучше.

Потом, если не нравится, что жрет много памяти, поставьте ограничение -Xmx<сколько вам надо>.

И софтина тупо рухнет при недостатке памяти.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

>И софтина тупо рухнет при недостатке памяти.
VM не должна выдавать OutOfMemoryError, если память еще можно освободить сборщиком мусора (правда, иногда выдает, если GC работает слишком долго). Соответственно, рухнет она только если у вас где-нибудь утечка указателей либо если на операцию объективно недостаточно памяти.

proud_anon ★★★★★
()
Ответ на: комментарий от Sadler

> И софтина тупо рухнет при недостатке памяти.
Не обязательно. Если программист использует SoftReferences

Вам уже объяснили - своей копеечной оптимизацией вы убивает рублевую оптимизацию GC. Если хочется возиться в памятью - пишите на языках, которые не managed.

svu ★★★★★
()
Ответ на: комментарий от Sadler

Я ещё не смотрел реализацию удаления объектов внутри GC


там нет никакого удаления объектов

Karapuz ★★★★★
()
Ответ на: комментарий от svu

> Кстати, спасибо, что не просите возможности вставлять асмовые вставки.

Ну, как бы есть native для этого.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Если ссылка была единственной, GC подчистит


Ты в курсе как он подчистит? Т.е. чтобы освободить 8 байт занятых объектом ты предлагаешь ему 2 Гига, занятых остальными, скопировать? оригинально

Karapuz ★★★★★
()

void finalize();

System.gc();

Обычно хватает практически на всё. Но без особой надобности, или без представления, зачем оно нужно, лучше не браться :)

при первом же обращении к удалённому участку можно выдать исключение с полным описанием проблемы


Ну да. Обычный NPE. 90% всех ошибок в моей практике :)

KRoN73 ★★★★★
()
Ответ на: комментарий от Deleted

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

Угу. Ибо даже в Си++ ненужные объекты — это сразу снижение скорости на один-два порядка: http://balancer.ru/tech/forum/2008/08/t63003--proizvoditelnost-yazykov-obektn...

KRoN73 ★★★★★
()
Ответ на: комментарий от Karapuz

> Ты в курсе как он подчистит? Т.е. чтобы освободить 8 байт занятых объектом ты предлагаешь ему 2 Гига, занятых остальными, скопировать? оригинально

Я ведь уже говорил, что опираюсь не на текущий алгоритм GC.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Во-первых VM не обязана исполнять System.gc()

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

KRoN73 ★★★★★
()
Ответ на: комментарий от Ingwar

>если машина мощная - так экономия ресурсов ненужна?

Лет, эдак, 15 назад, Андрей Черезов на предложение переписать ядро SP-Forth, так, чтобы в регистрах хранилась не одна вершина стека, а два верхних числа, что давало около 10-15% ускорения, ответил, дескать, пока он это всё будет переписывать, Intel выпустит новый процессор, который будет работать вдвое быстрее :)

Тогда меня это сильно покоробило, но с годами я тоже пришёл к выводу, что преждевременная оптимизация — зло :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

дескать, пока он это всё будет переписывать, Intel выпустит новый процессор, который будет работать вдвое быстрее


он уже 15 лет назад познал ДАО

Karapuz ★★★★★
()
Ответ на: комментарий от Karapuz

> а другие варианты бывают?

Обычно не бывает единственно верного алгоритма. Просто нужно придумывать, исследовать. Была бы цель.

Sadler ★★★
() автор топика
Ответ на: комментарий от svu

> Вот там память и освобождайте. Выделяйте и освобождайте, на здоровье:)

Если бы не кроссплатформенность, то это было бы самым простым решением.

Sadler ★★★
() автор топика
Ответ на: комментарий от Sadler

Тогда просто проникнитесь тем, что гс с поддержкой делете принципиально сильно тормознее гс без поддержки делете.

svu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.