ITEM 8: Avoid finalizer and cleaner

์ž๋ฐ”๋Š” finalizer, cleaner๋‘ ๊ฐ€์ง€ ๊ฐ์ฒด ์†Œ๋ฉธ์ž๋ฅผ ์ œ๊ณตํ•œ๋‹ค. finalizer์™€ cleaner๋Š” GC๊ฐ€ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ž์›์— ๋Œ€ํ•œ ์ •๋ฆฌ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

finalizer

  • ์˜ˆ์ธก์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ƒํ™ฉ์— ๋”ฐ๋ผ ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ์–ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆํ•„์š”

  • ์˜ค๋™์ž‘, ๋‚ฎ์€ ์„ฑ๋Šฅ, ์ด์‹์„ฑ ๋ฌธ์ œ์˜ ์›์ธ

finalizer ๋‚˜๋ฆ„์˜ ์“ฐ์ž„์ƒˆ๊ฐ€ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•ด์•ผํ•œ๋‹ค. (Java 9์—์„œ deprecated)

cleaner

cleaner๋Š” finalizer์˜ ๋Œ€์•ˆ์œผ๋กœ ์†Œ๊ฐœ๋˜์—ˆ๋‹ค. cleaner๋Š” finalizer๋ณด๋‹ค๋Š” ๋œ ์œ„ํ—˜ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์•„๋ž˜ ๋‹จ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

  • ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅ

  • ๋Š๋ฆผ

  • ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆํ•„์š”

์‚ฌ์šฉ์„ ์ง€์–‘ํ•ด์•ผํ•˜๋Š” ์ด์œ 

1. finalizer์™€ cleaner๋กœ๋Š” ์ œ๋•Œ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—…์€ ์ ˆ๋Œ€ ์•Œ ์ˆ˜ ์—†๋‹ค.

finalizer์™€ cleaner๋Š” ์ฆ‰์‹œ ์ˆ˜ํ–‰๋œ๋‹ค๋Š” ๋ณด์žฅ์ด ์—†์œผ๋ฉฐ, ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ฒŒ ๋œ ํ›„ finalizer์™€ cleaner๊ฐ€ ์‹คํ–‰๋  ๋•Œ๊นŒ์ง€ ์–ด๋Š์ •๋„ ๊ฑธ๋ฆฌ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŒŒ์ผ ๋‹ซ๊ธฐ๋ฅผ finalizer/ cleaner์— ๋งก๊ธฐ๊ฒŒ ๋œ๋‹ค๋ฉด ์‹œ์Šคํ…œ์ด ๋™์‹œ์— ์—ด ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ ๊ฐœ์ˆ˜์— ํ•œ๊ณ„๊ฐ€ ์žˆ๊ธฐ์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋ž˜์Šค์— finalizer๋ฅผ ๋‹ฌ์•„๋‘๋ฉด ์ธ์Šคํ„ด์Šค์˜ ์ž์› ํšŒ์ˆ˜๊ฐ€ ์ œ๋ฉ‹๋Œ€๋กœ ์ง€์—ฐ๋  ์ˆ˜ ์žˆ๋‹ค. ์‹ค์ œ๋กœ ์›์ธ์„ ์•Œ ์ˆ˜ ์—†๋Š” OutOfMemoryError๊ฐ€ ๋ฐœ์ƒํ•ด ๋ถ„์„ํ•ด๋ณด์•˜์„ ๋•Œ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ฃฝ๋Š” ์‹œ์ ์— ๊ฐ์ฒด ์ˆ˜์ฒœ๊ฐœ์˜ finalizer ์Šค๋ ˆ๋“œ๋Š” ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์Šค๋ ˆ๋“œ ๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚ฎ์•„ ๋Œ€๊ธฐ์—ด์—์„œ ํšŒ์ˆ˜๋˜๊ธฐ๋งŒ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์—ˆ๋‹ค. cleaner๋Š” ์ž์‹ ์ด ์ˆ˜ํ–‰ํ•  ์Šค๋ ˆ๋“œ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ ๋‚ซ์ง€๋งŒ, ์—ฌ์ „ํžˆ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ˆ˜ํ–‰๋˜๋ฉฐ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์˜ ํ†ต์ œํ•˜์— ์žˆ์–ด ์ฆ‰๊ฐ ์ˆ˜ํ–‰๋œ๋‹ค๋Š” ๋ณด์žฅ์ด ์—†๋‹ค. ๋˜ํ•œ, ์ž๋ฐ”๋Š” finalizer์™€ cleaner์˜ ์ˆ˜ํ–‰ ์‹œ์  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ˆ˜ํ–‰ ์—ฌ๋ถ€ ์กฐ์ฐจ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด๊ฒƒ์€ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ์ผ๋ถ€ ๊ฐ์ฒด์— ์ข…๋ฃŒ ์ž‘์—…์„ ์ „ํ˜€ ์ˆ˜ํ–‰ํ•˜์ง€ ๋ชปํ•œ ์ฑ„ ํ”„๋กœ๊ทธ๋žจ์ด ์ค‘๋‹จ ๋  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์ฆ‰, ์ƒํƒœ๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ์ˆ˜์ •ํ•˜๋Š” ์ž‘์—…์—์„œ ์ ˆ๋Œ€ finalizer์™€ cleaner์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

System.gc, System.runFinalization ์€ finalizer์™€ cleaner๊ฐ€ ์‹คํ–‰๋  ๊ฐ€๋Šฅ์„ฑ์€ ๋†’์—ฌ์ค„ ์ˆ˜ ์žˆ์œผ๋‚˜, ๋ณด์žฅํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉฐ, System.runFinalizersOnExit๊ณผ Runtime.runFinalizersOnExit์€ ์‹คํ–‰์„ ๋ณด์žฅํ•ด์ค€๋‹ค๊ณ  ๋˜์–ด์žˆ์ง€๋งŒ ThreadStop ์˜ ์‹ฌ๊ฐํ•œ ๊ฒฐํ•จ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

๋˜ํ•œ, finalizer๋Š” ๋™์ž‘ ์ค‘ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋Š” ๋ฌด์‹œ๋˜๋ฉฐ, ์ฒ˜๋ฆฌํ•  ์ž‘์—…์ด ๋‚จ์•„ ์žˆ๋”๋ผ๋„ ๊ทธ ์ˆœ๊ฐ„ ์ข…๋ฃŒ๋œ๋‹ค. ์žก์ง€ ๋ชปํ•œ ์˜ˆ์™ธ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๊ฐ์ฒด๋Š” ๋งˆ๋ฌด๋ฆฌ๊ฐ€ ๋œ ๋œ ์ƒํƒœ๋กœ ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ํ›ผ์†๋œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค ํ•œ๋‹ค๋ฉด, ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ• ์ง€ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋‹ค. (cleaner๋Š” ์ž์‹ ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ํ†ต์ œํ•˜๋ฏ€๋กœ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ ๋ฐœ์ƒ์•ˆํ•จ)

2. finalizer์™€ cleaner๋Š” ์‹ฌ๊ฐํ•œ ์„ฑ๋Šฅ ๋ฌธ์ œ๋„ ๋™๋ฐ˜๋  ์ˆ˜ ์žˆ๋‹ค.

AutoCloseable ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด GC๊ฐ€ ์ˆ˜๊ฑฐํ•˜๊ธฐ ๊นŒ์ง€ 12ns๊ฐ€ ๊ฑธ๋ฆฐ ๊ฒƒ์ด, finalizer๋ฅผ ์‚ฌ์šฉํ•˜๋‹ˆ 550ns๊ฐ€ ๊ฑธ๋ ธ๋‹ค. finalizer๊ฐ€ GC์˜ ํšจ์œจ์„ ๋–จ์–ด๋œจ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

cleaner๋„ ํด๋ž˜์Šค์˜ ๋ชจ๋“  ์ธ์Šคํ„ด์Šค๋ฅผ ์ˆ˜๊ฑฐํ•˜๋Š” ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜๋ฉด finalizer์™€ ์„ฑ๋Šฅ์€ ์œ ์‚ฌํ•˜๋ฉฐ, ์•ˆ์ •๋ง ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ์•ฝ 66ns๊ฐ€ ๊ฑธ๋ฆฌ๋‚˜, ์•ˆ์ „๋ง์„ ์„ค์น˜ํ•˜๋ฉด ์„ฑ๋Šฅ์ด ์•ฝ 5๋ฐฐ ์ •๋„ ๋Š๋ ค์ง„๋‹ค.

3. finalizer๋ฅผ ์‚ฌ์šฉํ•œ ํด๋ž˜์Šค๋Š” finalizer ๊ณต๊ฒฉ์— ๋…ธ์ถœ๋˜์–ด ์‹ฌ๊ฐํ•œ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

์ƒ์„ฑ์ž๋‚˜ ์ง๋ ฌํ™” ๊ณผ์ •์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, ์ƒ์„ฑ๋˜๋‹ค ๋งŒ ๊ฐ์ฒด์—์„œ ์•…์˜์ ์œผ๋กœ ํ•˜์œ„ ํด๋ž˜์Šค์˜ finalizer๊ฐ€ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ๋‹ค. ์ด finalizer๋Š” ์ •์  ํ•„๋“œ์— ์ž์‹ ์˜ ์ฐธ์กฐ๋ฅผ ํ• ๋‹นํ•ด GC๊ฐ€ ์ˆ˜์ง‘ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

๊ฐ์ฒด ์ƒ์„ฑ์„ ๋ง‰๊ธฐ์œ„ํ•ด ์ƒ์„ฑ์ž์—์„œ ์˜ˆ์™ธ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ, finalizer๊ฐ€ ์žˆ๋‹ค๋ฉด ์ด๋„ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

final์ด ์•„๋‹Œ ํด๋ž˜์Šค๋ฅผ finalizer ๊ณต๊ฒฉ์œผ๋กœ ๋ฐฉ์–ดํ•˜๋ ค๋ฉด ์•„๋ฌด ๋กœ์ง์ด ์—†๋Š” finalize ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“  ํ›„ final๋กœ ์„ ์–ธํ•˜๋ฉด ๋œ๋‹ค.

์‚ฌ์šฉํ•˜๋Š” ๊ณณ

  1. ์ž์›์˜ ์†Œ์œ ์ž๊ฐ€ close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์— ๋Œ€๋น„ํ•œ ์•ˆ์ •๋ง ์—ญํ• ๋กœ ์‚ฌ์šฉ (์–ธ์ œ ํšŒ์ˆ˜ ๋ ์ง€ ๋ชจ๋ฅด์ง€๋งŒ ๋Šฆ๊ฒŒ๋ผ๋„ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹์Œ ) - FileInputStream, FileOutputStream, ThreadPoolExecutor์—์„œ ์•ˆ์ „๋ง ์—ญํ• ์˜ finalizer ์ œ๊ณต

  2. *Native Peer๋Š” ์ž๋ฐ” ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ GC๊ฐ€ ๊ทธ ์กด์žฌ๋ฅผ ์•Œ์ง€ ๋ชปํ•œ๋‹ค. ์ฆ‰, ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด์™€ ์—ฐ๊ฒฐ๋œ ๊ฐ์ฒด์—์„œ์˜ ์ž์› ํšŒ์ˆ˜์šฉ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ๋‹จ, ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๊ฐ๋‹นํ•  ์ˆ˜ ์žˆ๊ณ  ๋„ค์ดํ‹ฐ๋ธŒ ํ”ผ์–ด๊ฐ€ ์‹ฌ๊ฐํ•œ ์ž์›์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์„ ๋•Œ๋งŒ ํ•ด๋‹นํ•œ๋‹ค. ์„ฑ๋Šฅ์ €ํ•˜๋ฅผ ๊ฐ๋‹นํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜ ์ž์›์„ ์ฆ‰์‹œ ํšŒ์ˆ˜ํ•ด์•ผํ•œ๋‹ค๋ฉด close ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

cleaner๋Š” ์•ˆ์ „๋ง ์—ญํ• ์ด๋‚˜ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๋„ค์ดํ‹ฐ๋ธŒ ์ž์› ํšŒ์ˆ˜ ์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด ๊ฒฝ์šฐ์—๋„ ๋ถˆํ™•์‹ค์„ฑ๊ณผ ์„ฑ๋Šฅ์ €ํ•˜์— ์œ ์˜ํ•ด์•ผํ•œ๋‹ค.

\ Native Peer : ์ผ๋ฐ˜ ์ž๋ฐ” ๊ฐ์ฒด๊ฐ€ ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ธฐ๋Šฅ์„ ์œ„์ž„ํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ๊ฐ์ฒด*

๋Œ€์•ˆ

ํŒŒ์ผ์ด๋‚˜ ์Šค๋ ˆ๋“œ ๋“ฑ ์ข…๋ฃŒํ•ด์•ผ ํ•  ์ž์›์„ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์˜ ํด๋ž˜์Šค์—์„œ finalizer์™€ cleaner๋ฅผ ๋Œ€์‹ ํ•ด์ฃผ๋ ค๋ฉด AutoCloseable์„ ๊ตฌํ˜„ํ•ด์ฃผ๊ณ , close ๋ฉ”์„œ๋“ค๋ฅด ํ˜ธ์ถœํ•˜๋ฉด๋œ๋‹ค.(try-with-resources(item 9))

๊ฐ ์ธ์Šคํ„ด์Šค๋Š” close ๋ฉ”์„œ๋“œ์—์„œ ๋” ์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š์Œ์„ ๊ธฐ๋กํ•˜๊ณ , ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋Š” ํ•ด๋‹น ํ•„๋“œ๋ฅผ ๊ฒ€์‚ฌํ•ด ๊ฐ์ฒด๊ฐ€ ๋‹ซํžŒ ํ›„์— ํ˜ธ์ถœํ–ˆ๋‹ค๋ฉด IllegalStateException ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค.

์ฐธ๊ณ 

Last updated