{"componentChunkName":"component---src-templates-post-template-jsx","path":"/history/posts/2020-10-04--003--07","result":{"data":{"site":{"siteMetadata":{"title":"Blog by Eunyoung","subtitle":"작업 기록 블로그","copyright":"© All rights reserved.","author":{"name":"EunYoung","twitter":"#"},"disqusShortname":"","url":"https://ssongey.github.io"}},"markdownRemark":{"id":"cac9a5da-ed40-5f07-9574-60c05fa28fb8","html":"<h2>아이템7) 다 쓴 객체 참조를 해제하라</h2>\n<p>메모리 누수는 겉으로 잘 드러나지 않아 시스템에 수년간 잠복하는 사례도 있다.<br>\n이런 누수는 철저한 코드 리뷰나 힙 프로파일러 같은 디버깅 도구를 동원해야만 발견되기도 한다.<br>\n그래서 이런 종류의 문제는 예방법을 익혀두는 것이 매우 중요하다.</p>\n<h4>메모리 누수 발생 코드</h4>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Stack</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">private</span> <span class=\"token class-name\">Obejct</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> elements<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">int</span> size <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">final</span> <span class=\"token keyword\">int</span> DEFAULT_INITIAL_CAPACITY <span class=\"token operator\">=</span> <span class=\"token number\">16</span><span class=\"token punctuation\">;</span>\n  \n  <span class=\"token keyword\">public</span> <span class=\"token class-name\">Stack</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    elements <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Object</span><span class=\"token punctuation\">[</span>DEFAULT_INITIAL_CAPACITY<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> \n  <span class=\"token punctuation\">}</span>\n  \n  <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Object</span> e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">ensureCapacity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    elements<span class=\"token punctuation\">[</span>size<span class=\"token operator\">++</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> e<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">public</span> <span class=\"token class-name\">Object</span> <span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>size <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">EmptyStackException</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> elements<span class=\"token punctuation\">[</span><span class=\"token operator\">--</span>size<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  \n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">void</span> <span class=\"token function\">ensureCapacity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>elements<span class=\"token punctuation\">.</span>length <span class=\"token operator\">==</span> size<span class=\"token punctuation\">)</span>\n      elements <span class=\"token operator\">=</span> <span class=\"token class-name\">Arrays</span><span class=\"token punctuation\">.</span><span class=\"token function\">copyOf</span><span class=\"token punctuation\">(</span>elements<span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token operator\">*</span>size<span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h4>해결방법</h4>\n<ul>\n<li>Object[]은 Arrays.copyOf()를 통해 길이조절이 되는 상황이다.<br>\npop() 메소드에서 size를 감소시키나, 해당 값은 그대로 두고 있으므로 메모리 누수가 발생하는 것을 볼 수 있다.<br>\n이 경우 명시적으로 null 을 할당해줌으로써 참조해제를 통해 GC를 돌릴 수 있다.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">  <span class=\"token keyword\">public</span> <span class=\"token class-name\">Object</span> <span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>size <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">EmptyStackException</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">Object</span> result <span class=\"token operator\">=</span> elements<span class=\"token punctuation\">[</span><span class=\"token operator\">--</span>size<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    elements<span class=\"token punctuation\">[</span>size<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 참조값인데.... result도 null이 아닌가?? 확인 필요</span>\n    <span class=\"token keyword\">return</span> result<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<h4>메모리 누수 주범</h4>\n<ul>\n<li>자기 메모리를 직접 관리하는 클래스</li>\n<li>캐시</li>\n<li>리스너 혹은 콜백</li>\n</ul>\n<h4>메모리 누수 예방법</h4>\n<ul>\n<li>원소를 다 사용한 즉시 그 원소가 참조한 객체들을 null 처리 한다.</li>\n<li>WeakHashMap 또는 LinkedHashMap의 removeEldestEntry() 를 사용</li>\n<li>백그라운드 스레드 활용 (ScheduledThreadPoolExecutor)</li>\n</ul>\n<h5>참고</h5>\n<ul>\n<li><a href=\"http://blog.breakingthat.com/2018/08/26/java-collection-map-weakhashmap/\">WeakHashMap (약한 참조 해시맵)</a></li>\n<li><a href=\"https://javafactory.tistory.com/735\">LinkedHashMap.removeEldestEntry()</a></li>\n</ul>","fields":{"tagSlugs":["/tags/책리뷰/","/tags/이펙티브자바/"],"slug":"/history/posts/2020-10-04--003--07"},"frontmatter":{"title":"[책리뷰/Effective Java] 객체 생성과 파괴","tags":["책리뷰","이펙티브자바"],"date":"2020-10-04","description":"아이템7) 다 쓴 객체 참조를 해제하라"}}},"pageContext":{"slug":"/history/posts/2020-10-04--003--07"}},"staticQueryHashes":[]}