2009-04-29 2 views
1

При попытке открыть размер макс массива Java Струнный на моей машине, я натолкнулся на некоторые интересные результаты, вот код,Что происходит с распределением памяти здесь?

String [] max; 
    int i = 15444000; 
    while(true){ 
     try{ 
     max = new String[i]; 
     System.gc(); 
     Thread.sleep(10); 
     }catch(InterruptedException e){} 
    i += 1; 
    System.out.println(i); 
    } 

Всякий раз, когда я запускаю этот код на выходе делает его перед броском OutOfMemoryError. Это заставляет меня думать, что размер максимум из массива Java Струнный на моей машине , однако, если я заменить

int i = 15444000; 

с

int i = 15444037; // or any i between 15444037 and 15444002 

OutOfMemoryError происходит мгновенно. Почему это, и каков истинный максимальный размер массива Java String на моей машине?

+0

Сколько памяти вы выделили для JVM? – CookieOfFortune

+0

Как указывает Печенье, GC настолько непредсказуем, что такой тест, наконец, не означает многого. –

+0

И что вы на самом деле пытаетесь проверить? Количество элементов, которые вы можете иметь в массиве? Здесь не было никакой разницы между String [] и Object [] или чем-либо еще, поскольку вы просто создаете пространство для ссылки ... Вы пытаетесь выяснить максимальный размер строки? Разве Java не требует, чтобы массивы занимали непрерывное пространство? Тогда вы получите разные ответы за все время работы виртуальной машины, что находится в perm gen и т. Д. –

ответ

2

Максимальный размер массива, который вы сможете выделить, зависит от того, насколько велика максимальная память для виртуальной машины. Вы можете изменить максимум с помощью -Xmxcommand line argument.

Также http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#gc() состояния

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

Так что ваше расхождение может быть, потому что GC не вычистил таким же образом, каждый раз, когда (виртуальная машина языка Ява сделала все возможное, чтобы вернуть себе место).

1

Я думаю, что может произойти, и это просто предположение, что JIT (Just in time compiler) может оптимизировать часть памяти? Вторая догадка заключается в том, что сбор мусора высвобождает только немного памяти, прежде чем цикл снова будет запущен. Попробуйте добавить сбор мусора, прежде чем выделять массив.

-1

Ну, вы могли бы спорить много, но я думаю, что правильный ответ: «Кому это нужно?». Ответ на ваш вопрос о том, какой максимум с вашей конфигурацией, составляет «около 15 миллионов». Если вы действительно хотите беспокоиться о распределении кучи до последних 4 байтов, программа в ассемблере ...

P.S. Вещи, которые могли бы иметь, включают объекты, используемые на ранней стадии в потоке обслуживания, который становится сборщиком мусора, как только программа работает немного. Еще одно явление JIT-оптимизации, которое намекает еще один плакат, также потенциально возможно: есть некоторые потоки, которые начинают выделять небольшие объекты в куче, а затем в какой-то момент JIT-оптимизируются, чтобы «распределять» их в регистры/стек. Но, честно говоря, если вы не обнаружите, что размер массива, который вы можете выделить внезапно половину, я бы не стал слишком беспокоиться об этом.

+0

Я не беспокоюсь об этом, на самом деле мне больше не понадобится создавать массив такого размера. Я просто развлекаюсь с Java. – ForYourOwnGood

+0

Ну, справедливо, я добавил несколько возможных объяснений в свой ответ, но моя точка зрения также довольно серьезная: вы действительно не должны ожидать, что сможете учесть все до последнего байта, и это тоже своего рода «объяснение». –

+0

Кто сказал, что «вы не сможете учесть вещи до последнего байта»? Это компьютерная * наука *, никакое программирование культа груза ... – Hejazzman

0

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

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

0

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

Еще одна вещь, о которой стоит знать: вызов System.gc() не означает, что сборщик мусора работает. Это всего лишь предложение.

Смежные вопросы