<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## Chapter 2. Creating and Destroying Objects(創建和銷毀對象) ### Item 7: Eliminate obsolete object references(排除過時的對象引用) If you switched from a language with manual memory management, such as C or C++, to a garbage-collected language such as Java, your job as a programmer was made much easier by the fact that your objects are automatically reclaimed when you’re through with them. It seems almost like magic when you first experience it. It can easily lead to the impression that you don’t have to think about memory management, but this isn’t quite true. 如果你從需要手動管理內存的語言(如 C 或 c++)切換到具有垃圾回收機制的語言(如 Java),當你使用完對象后,會感覺程序員工作輕松很多。當你第一次體驗它的時候,它幾乎就像魔術一樣。這很容易讓人覺得你不需要考慮內存管理,但這并不完全正確。 Consider the following simple stack implementation: 考慮以下簡單的堆棧實現: ``` import java.util.Arrays; import java.util.EmptyStackException; // Can you spot the "memory leak"? public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } /** * Ensure space for at least one more element, roughly * doubling the capacity each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } } ``` There’s nothing obviously wrong with this program (but see Item 29 for a generic version). You could test it exhaustively, and it would pass every test with flying colors, but there’s a problem lurking. Loosely speaking, the program has a”memory leak,” which can silently manifest itself as reduced performance due to increased garbage collector activity or increased memory footprint. In extreme cases, such memory leaks can cause disk paging and even program failure with an OutOfMemoryError, but such failures are relatively rare. 這個程序沒有明顯的錯誤(但是通用版本請參閱 [Item-29](/Chapter-5/Chapter-5-Item-29-Favor-generic-types.md))。你可以對它進行詳盡的測試,它會以優異的成績通過所有的測試,但是有一個潛在的問題。簡單地說,該程序有一個「內存泄漏」問題,由于垃圾收集器活動的增加或內存占用的增加,它可以悄無聲息地表現為性能的降低。在極端情況下,這種內存泄漏可能導致磁盤分頁,甚至出現 OutOfMemoryError 程序故障,但這種故障相對少見。 So where is the memory leak? If a stack grows and then shrinks, the objects that were popped off the stack will not be garbage collected, even if the program using the stack has no more references to them. This is because the stack maintains obsolete references to these objects. An obsolete reference is simply a reference that will never be dereferenced again. In this case, any references outside of the “active portion” of the element array are obsolete. The active portion consists of the elements whose index is less than size. 那么內存泄漏在哪里呢?如果堆棧增長,然后收縮,那么從堆棧中彈出的對象將不會被垃圾收集,即使使用堆棧的程序不再引用它們。這是因為棧保留了這些對象的舊引用。一個過時的引用,是指永遠不會被取消的引用。在本例中,元素數組的「活動部分」之外的任何引用都已過時。活動部分由索引小于大小的元素組成。 Memory leaks in garbage-collected languages (more properly known as unintentional object retentions) are insidious. If an object reference is unintentionally retained, not only is that object excluded from garbage collection, but so too are any objects referenced by that object, and so on. Even if only a few object references are unintentionally retained, many, many objects may be prevented from being garbage collected, with potentially large effects on performance. 垃圾收集語言中的內存泄漏(更確切地說是無意的對象保留)是暗藏的風險。如果無意中保留了對象引用,那么對象不僅被排除在垃圾收集之外,該對象引用的任何對象也被排除在外,依此類推。即使只是無意中保留了一些對象引用,許多許多的對象也可能被阻止被垃圾收集,從而對性能產生潛在的巨大影響。 The fix for this sort of problem is simple: null out references once they become obsolete. In the case of our Stack class, the reference to an item becomes obsolete as soon as it’s popped off the stack. The corrected version of the pop method looks like this: 解決這類問題的方法很簡單:一旦引用過時,就將置空。在我們的 Stack 類中,對某個項的引用一旦從堆棧中彈出就會過時。pop 方法的正確版本如下: ``` public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // Eliminate obsolete reference return result; } ``` An added benefit of nulling out obsolete references is that if they are subsequently dereferenced by mistake, the program will immediately fail with a NullPointerException, rather than quietly doing the wrong thing. It is always beneficial to detect programming errors as quickly as possible. 用 null 處理過時引用的另一個好處是,如果它們隨后被錯誤地關聯引用,程序將立即失敗,出現 NullPointerException,而不是悄悄地做錯誤的事情。盡可能快地檢測編程錯誤總是有益的。 When programmers are first stung by this problem, they may overcompensate by nulling out every object reference as soon as the program is finished using it.This is neither necessary nor desirable; it clutters up the program unnecessarily.Nulling out object references should be the exception rather than the norm.The best way to eliminate an obsolete reference is to let the variable that contained the reference fall out of scope. This occurs naturally if you define each variable in the narrowest possible scope (Item 57). 當程序員第一次被這個問題困擾時,他們可能會過度擔心,一旦程序使用完它,他們就會取消所有對象引用。這既無必要也不可取;它不必要地搞亂了程序。清除對象引用應該是例外,而不是規范。消除過時引用的最佳方法是讓包含引用的變量脫離作用域。如果你在最狹窄的范圍內定義每個變量([Item-57](/Chapter-9/Chapter-9-Item-57-Minimize-the-scope-of-local-variables.md)),那么這種情況自然會發生。 So when should you null out a reference? What aspect of the Stack class makes it susceptible to memory leaks? Simply put, it manages its own memory.The storage pool consists of the elements of the elements array (the object reference cells, not the objects themselves). The elements in the active portion of the array (as defined earlier) are allocated, and those in the remainder of the array are free. The garbage collector has no way of knowing this; to the garbage collector, all of the object references in the elements array are equally valid.Only the programmer knows that the inactive portion of the array is unimportant.The programmer effectively communicates this fact to the garbage collector by manually nulling out array elements as soon as they become part of the inactive portion. 那么,什么時候應該取消引用呢?Stack 類的哪些方面容易導致內存泄漏?簡單地說,它管理自己的內存。存儲池包含元素數組的元素(對象引用單元,而不是對象本身)數組的活動部分(如前面所定義的)中的元素被分配,而數組其余部分中的元素是空閑的。垃圾收集器沒有辦法知道這一點;對于垃圾收集器,元素數組中的所有對象引用都同樣有效。只有程序員知道數組的非活動部分不重要。只要數組元素成為非活動部分的一部分,程序員就可以通過手動清空數組元素,有效地將這個事實傳遞給垃圾收集器。 Generally speaking, whenever a class manages its own memory, the programmer should be alert for memory leaks. Whenever an element is freed,any object references contained in the element should be nulled out. 一般來說,一個類管理它自己的內存時,程序員應該警惕內存泄漏。當釋放一個元素時,該元素中包含的任何對象引用都應該被置為 null。 Another common source of memory leaks is caches. Once you put an object reference into a cache, it’s easy to forget that it’s there and leave it in the cache long after it becomes irrelevant. There are several solutions to this problem. If you’re lucky enough to implement a cache for which an entry is relevant exactly so long as there are references to its key outside of the cache, represent the cache as a WeakHashMap; entries will be removed automatically after they become obsolete. Remember that WeakHashMap is useful only if the desired lifetime of cache entries is determined by external references to the key, not the value. 另一個常見的內存泄漏源是緩存。一旦將對象引用放入緩存中,就很容易忘記它就在那里,并且在它變得無關緊要之后很久仍將它留在緩存中。有幾個解決這個問題的辦法。如果你非常幸運地實現了一個緩存,只要緩存外有對其鍵的引用,那么就將緩存表示為 WeakHashMap;當條目過時后,條目將被自動刪除。記住,WeakHashMap 只有在緩存條目的預期生存期由鍵的外部引用(而不是值)決定時才有用。 More commonly, the useful lifetime of a cache entry is less well defined, with entries becoming less valuable over time. Under these circumstances, the cache should occasionally be cleansed of entries that have fallen into disuse. This can be done by a background thread (perhaps a ScheduledThreadPoolExecutor) or as a side effect of adding new entries to the cache. The LinkedHashMap class facilitates the latter approach with its removeEldestEntry method. For more sophisticated caches, you may need to use java.lang.ref directly. 更常見的情況是,緩存條目的有效生存期定義不太好,隨著時間的推移,條目的價值會越來越低。在這種情況下,緩存偶爾應該清理那些已經停用的條目。這可以通過后臺線程(可能是 ScheduledThreadPoolExecutor)或向緩存添加新條目時順便完成。LinkedHashMap 類通過其 removeEldestEntry 方法簡化了后一種方法。對于更復雜的緩存,你可能需要直接使用 java.lang.ref。 **A third common source of memory leaks is listeners and other callbacks.** If you implement an API where clients register callbacks but don’t deregister them explicitly, they will accumulate unless you take some action. One way to ensure that callbacks are garbage collected promptly is to store only weak references to them, for instance, by storing them only as keys in a WeakHashMap. **內存泄漏的第三個常見來源是偵聽器和其他回調。** 如果你實現了一個 API,其中客戶端注冊回調,但不顯式取消它們,除非你采取一些行動,否則它們將累積。確保回調被及時地垃圾收集的一種方法是僅存儲對它們的弱引用,例如,將它們作為鍵存儲在 WeakHashMap 中。 Because memory leaks typically do not manifest themselves as obvious failures, they may remain present in a system for years. They are typically discovered only as a result of careful code inspection or with the aid of a debugging tool known as a heap profiler. Therefore, it is very desirable to learn to anticipate problems like this before they occur and prevent them from happening. 由于內存泄漏通常不會表現為明顯的故障,它們可能會在系統中存在多年。它們通常只能通過仔細的代碼檢查或借助一種稱為堆分析器的調試工具來發現。因此,學會在這樣的問題發生之前預測并防止它們發生是非常可取的。 --- **[Back to contents of the chapter(返回章節目錄)](/Chapter-2/Chapter-2-Introduction.md)** - **Previous Item(上一條目):[Item 6: Avoid creating unnecessary objects(避免創建不必要的對象)](/Chapter-2/Chapter-2-Item-6-Avoid-creating-unnecessary-objects.md)** - **Next Item(下一條目):[Item 8: Avoid finalizers and cleaners(避免使用終結器和清除器)](/Chapter-2/Chapter-2-Item-8-Avoid-finalizers-and-cleaners.md)**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看