2016-07-12 3 views
2
public class Currency { 
    String name = new String(); 
    static Integer value = new Integer(); 
    static void getCurrency(Integer v) { 
     Currency c = new Currency(); 
     c.value = v; 
    } 
    public static void m() { 
     Currency.getCurrency(50); 
     Currency.getCurrency(100); 
    } 
    public static void main(String[] argv) { 
     Currency.m(); 
    } 
} 

Рассчитывает 5 элементов, имеющие право на сборщик мусора, когда m() выходов. Упражнение гласит, что 6 - правильный ответ. Вы можете мне помочь?Сколько объектов имеют право на сборщик мусора в данном примере

+0

Можете ли вы рассказать нам, какие 5 переменных вы считали подходящими для сбора мусора? –

+0

Два объекта «Валюта», созданных в getCurrency, для каждого из этих объектов в куче создается строка «имя» (нестатическая). Затем я подумал, что c.value просто изменит содержимое статического целочисленного значения, но похоже, что я ошибаюсь в этой последней части? – user1365914

+1

Это вопрос трюка: никакие объекты не подходят для GC, потому что не создаются никакие объекты, учитывая, что 'new Integer()' вызывает 'Ошибка компиляции конструктора Integer() не определена, и, следовательно, предотвращает запуск кода. – Andreas

ответ

1

Два звонка, сделанные в getCurrency(), будут создавать дваCurrency объектов в общей сложности. Каждый вызов требует:

  • в Integer объекте в качестве параметра, позже назначенного value
  • Currency объекта
  • name строки объекта (не static, то есть каждый Currency объекта имеет один)

3 × 2 = 6

Обновление ate:

Большой вопрос заключается в том, будет ли создан новый объект Integer для каждого вызова конструктора Currency. Автобоксирование примитива int в Integer вызовет Integer.valueOf(). И Javadoc это сказать о Integer.valueOf():

Возвращает экземпляр Integer, представляющий указанное значение INT. Если новый экземпляр Integer не требуется, этот метод обычно должен использоваться в предпочтении конструктору Integer (int), так как этот метод может значительно улучшить производительность пространства и времени, кэшируя часто запрашиваемые значения. Этот метод всегда будет кэшировать значения в диапазоне от -128 до 127 включительно и может кэшировать другие значения за пределами этого диапазона.

Значения в диапазоне от -128 до 127 получают кеширование. Но улов в том, что в вашем коде вы работаете с двумя разными значениями: 50 и 100, поэтому кэширование не позволит избежать создания нового объекта AFAIK Integer.

+1

Каждый вызов, сделанный в 'getCurrency()', создаст * один * объект Currency. Таким образом, вызов 'm()' создает * два * Объекта Currency. – Andreas

+0

Но не должны ли значения «Целое» в этом примере быть частью кеша «Целое» и поэтому не иметь права на сбор мусора? – resueman

+0

@resueman Целочисленный класс непреложный – Kode

0

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

Вот объекты, на которые ссылаются программе:

  1. Integer # 0 - The Integer создан static Integer value = new Integer() *
  2. Currency # 1 - Currency созданный Currency.getCurrency(50).
  3. Integer # 1 - Integer, возвращенный автообоксированием 50.
  4. String # 1 - String создатель: String name = new String() в Currency # 1 создание.
  5. Currency # 2 - Currency создатель: Currency.getCurrency(100).
  6. Integer # 2 - Integer, возвращенный автообоксированием 100.
  7. String # 2 - String создатель: String name = new String() в Currency # 2 создание.

* Это фактически не компилируется, но я предполагаю, что он заменен действительным кодом, который не влияет на программу.


Таким образом, для вашего кода необходимо семь объектов. Первоначально объект, на который ссылается value, получает право на сбор мусора, когда value заменяется на 50. Первый и второй Currency s имеют право на конец m, когда их единственные ссылки выходят за рамки. Первый и второй String s имеют право на конец m, когда их только объекты-ссылки, Currency с 1 и 2, выходят за рамки. Автобокс Integer от 100, очевидно, по-прежнему ссылается в конце на статическую ссылку value и поэтому не имеет права на сбор мусора. Это 5 объектов, имеющих право на участие, 1 неприемлемых и еще не обсужденных.

Последний объект: Integer, возвращенный autoboxing из 50. Ваш код, очевидно, больше не ссылается на него, так как value вместо этого ссылается на 100. Это, по-видимому, указывает на то, что оно имеет право на сбор мусора, но я не согласен. Integer класс is know to cache values at least in the range -128 to 127, чтобы соответствовать JLS 5.1.7. Поэтому, когда выйдет m, кеш по-прежнему будет содержать ссылку на коробку Integer от 50, в результате чего она будет непригодна для сбора мусора.


Я попытался проверить это поведение с помощью этой программы:

public class Test{ 
    public static final WeakReference<Integer> inCache = new WeakReference<>(50); 
    public static final WeakReference<Integer> outOfCache = new WeakReference<>(10000); 
    public static void main(String[] args){ 
     System.gc(); 
     System.out.println(inCache.get()); 
     System.out.println(outOfCache.get()); 
    } 
} 

который выводит

50 
null 

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

Я признаю, что это ничего не доказывает, так как для одного System.gc() не гарантирует, что он будет собирать всю (или любую) доступную память. Тем не менее, я думаю, это должно показать, что проблема не такая простая, как можно было бы предположить, и, по наиболее распространенным JDK/JVM, вполне вероятно, что шестое значение не подходит для сбора мусора.


TL; DR - Я не думаю, что Integer возвращаемый бокс 50 имеет право на сбор мусора, потому что она по-прежнему ссылается на кэш, поддерживаемой Integer класса.

+0

Вы совершенно правы, за исключением того, что это, скорее всего, неправильный ответ для упражнений. Я говорю, что, поскольку моя оценка заключается в том, что вся концепция кеширования объектов с ядром Integer превышает теоретические знания людей, выполняющих упражнения. Если вы игнорируете внутреннюю оптимизацию объектов в квадрате «Integer», ответ будет равен 6. Если вы учитываете кеширование, ответ будет равен 5. Если вы учитываете ошибку компиляции в вопросе, ответ равен 0 или N/A, в зависимости от того, что вы предпочитаете. – Andreas

+0

Все это подчеркивается искажением в вашем ответе. Вы говорите * «Целое число, созданное автобоксацией 50/100» *, что указывает на то, что там создан объект Integer. На самом деле кеш «Integer» предварительно создан, а неявный 'Integer.valueOf()', который делает autoboxing, просто возвращает * уже существующий * кешированный объект. Поэтому, если ваш аргумент заключается в том, что кэширование означает, что ответ равен 5, то, по крайней мере, опишите причину, почему правильно. – Andreas

+0

@Andreas Я не чувствую, что время создания 'Integer' имеет отношение к моей точке. Кэш, который лениво создает значения по мере необходимости (когда неявный 'Integer.valueOf' вызывается в этом случае), по-прежнему будет содержать кешированную ссылку в конце. Я не сказал, что имею в виду, но моя ошибка не влияет на точку ответа. – resueman

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