์๋ฐ์ String๊ณผ Constant Pool
by JiwonDev#1. JVM
์ด์์ฒด์ ์ ํ๋์จ์ด์ ๋ ๋ฆฝ์ ์ธ ์ธ์ด, 1995๋ ๋น์ ์ด ๊ฐ๋ ์ ํ๋ก๊ทธ๋๋ฐ์ ํ์ ์ด์๋ค. ์ฐธ๊ณ ๋ก ์๋ฐ๋ ์ฌ ๋ง์ดํฌ๋ก์์คํ ์ค๊ฐ ๊ฐ๋ฐํ์ง๋ง JVM ๋ช ์ธ(Specification)๋ง ๋ฐ๋ฅธ๋ค๋ฉด ๋๊ตฌ๋ ๊ฐ๋ฐํด์ JVM
jiwondev.tistory.com
Java์ฝ๋๋ฅผ ์ปดํ์ผํ๋ฉด ํด๋์ค๋จ์ ๋ฐ์ดํธ์ฝ๋(.class)๋ก ๋ณํ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น ๋ฐ์ดํธ ์ฝ๋๋ฅผ JVM์ ์คํ์ํค๋ฉด Static(Method), Heap, Stack๋ก ๋๋ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๋ค.
๊ทธ ์ค Method Area (=Static Area)์์๋ ๊ฐ ํด๋์ค ๋ณ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ณ ์ ์ ๋ณด๋ฅผ ์ ์ฅํฉ๋๋ค. ์ ์ ๊ณต๊ฐ์ด๋ผ๋ ์ด๋ฆ ๋ต๊ฒ ํ๋ก๊ทธ๋จ์ด ์ข ๋ฃ ๋ ๋๊น์ง ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์์ต๋๋ค. (์ด ์์ญ์์๋ GC๊ฐ ๋์ํ์ง ์์ต๋๋ค.)
- file data(ํ๋ ๋ฐ์ดํฐ) : ๋ฉค๋ฒ ๋ณ์์ด๋ฆ, ํ์ , ์ ๊ทผ์ ์ด์๋ฑ์ ๋ฉํ์ ๋ณด
- method data(๋ฉ์๋ ๋ฐ์ดํฐ) : ๋ฉ์๋ ์ด๋ฆ, ๋ฆฌํดํ์ , ๋งค๊ฐ๋ณ์, ์ ๊ทผ์ ์ด์๋ฑ์ ๋ฉํ์ ๋ณด
- constructor(์์ฑ์) : ์์ฑ์ ๋ฉ์๋์ ๊ดํ ์ ๋ณด.
- static ๋ณ์(Class ๋ณ์) : ๋ชจ๋ ๊ฐ์ฒด๊ฐ ๊ณต์ ํ ์ ์๋ ์ ์ ํด๋์ค ๋ณ์.
- runtime constant pool (๋ฐํ์ ์์ ํ)
#์์์ ๋ฆฌํฐ๋(literal)
์์์ ๋ฆฌํฐ๋์ ํท๊ฐ๋ฆด ์ ์๋๋ฐ, ์์๋ '์ด๊ธฐํ ์ดํ ๊ฐ์ด ๋ณํ์ง ์๋ ์' ์ด๋ค. ๋ณ์๋ฅผ ์ ์ธ ํ ๋ final ํค์๋๋ฅผ ์ด์ฉํด ์์๋ก ๋ง๋ค ์ ์๋ค.
final int DAY_OF_WEEK = 7; // ์ฐธ๊ณ ) ๊ฐ๋ฅํ๋ฉด ์์๊ฐ์ get ๋ฉ์๋๋ก ์ ๊ณตํ๋๊ฒ ์ข์ต๋๋ค.
๋ฆฌํฐ๋๋ ์์์ ์ผ์ข ์ธ๋ฐ, ๋ง ๊ทธ๋๋ก ์ ์ธ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋, ๋ฌธ์ ๊ทธ๋๋ก์(=๋ฆฌํฐ๋ํ) ์์๋ฅผ ์๋ฏธํ๋ค. immediate value ๋ผ๊ณ ํ๊ธฐ๋ ํ๋ค.
3
"HEllO"
3.213
'H'
๋ณ์๋ก ์ ์ธํ์ง ์๊ณ ๋ฐ๋ก ์์๋ก ์ฌ์ฉํ๋ ๊ฐ๋ค๋ ๊ณ ์ ์ ๋ฐ์ดํฐ ํ์ ์ ๊ฐ์ง๋ค.
์ฐธ๊ณ ๋ก ๋ฆฌํฐ๋ ๋ค์ (L, F, D)๊ฐ์ ํค์๋๋ฅผ ๋ถ์ฌ ๋ช ์์ ์ผ๋ก ํด๋น ๋ฆฌํฐ๋์ ํ์ ์ ์ง์ ํด์ค ์ ์๋ค.
object.setNumber(3) // ๋ฆฌํฐ๋ '3'์ ์๋ฃํ์ int์ด๋ค.
object.setName("Hello") // ๋ฆฌํฐ๋ "Hello"์ ํด๋์ค๋ String์ด๋ค.
object.setNumber(3.0) // ๋ฆฌํฐ๋ '3.0'์ ์๋ฃํ์ int..? float..? double..?
object.setNumber(3.0F) // ์ด๋ ๊ฒ ๋ช
์์ ์ผ๋ก Floatํ ์ด๋ผ๊ณ ์ ํด ์ค ์ ์๋ค.
int a = 1 // ์์์ ์ด ์์ผ๋ฉด intํ ๋ฆฌํฐ๋์ด๋ค. ๋ฐ๋ก ๋ฆฌํฐ๋ ํ์๋ฅผ ํ์ง ์์๋ ๋๋ค.
boolean b = true // boolean์ ๊ฐ์ด true, false 2๊ฐ๋ฐ์ ์์ด ๋ฐ๋ก ๋ฆฌํฐ๋ ํ์๋ฅผ ์ํด๋ ๋๋ค.
// ์ค์ ๋ฆฌํฐ๋์ ์ฌ์ฉํ ๋๋ ๋ฐ๋์ ๋ช
์์ ์ผ๋ก ํ์ํด์ฃผ์.
long count = 10000L;
float f1 = 2.3F;
double d1 = 5.6D;
# ์ฐธ์กฐํ(Reference)
ํด๋์ค๋ฅผ ์ ์ํ๊ณ new ํค์๋๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑ ํ ์ ์๋ค.
์๋ฐ์์๋ ๊ธฐ๋ณธ ์๋ฃํ์ ์ ์ธํ ๋ชจ๋ ๊ฒ์ ์ฐธ์กฐํ์ผ๋ก ์ฌ์ฉํ๋ค. ์คํดํ์ง ๋ง์์ผ ํ๋๊ฒ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ์ ๊ฐ์ง๊ณ ์๋๊ฒ ์๋๋ผ ์ฌ๋ณผ(=์ด๋ฆ)๋ง ๊ฐ์ง๊ณ ์๋ค. ์ฌ๋ณผ์ ์ด์ฉํด์ ์คํํ๋ ์์ ์ JVM์ด ํด๋น ์ฌ๋ณผ์ด ์ ์ฅ๋์ด์๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ์ ๊ทผํ๋ค.
//ํด๋์ค์ด๋ฆ ๋ ํผ๋ฐ์ค๋ช
= new ํด๋์ค์ด๋ฆ();
MadPlay instance = new MadPlay();
# String ํด๋์ค
์๋ฐ์์๋ ๋ฌธ์์ด์ด ํด๋์ค๋ก ์ ๊ณต๋์ด์ง๋ค. ํ์ง๋ง String ๊ฐ์ฒด์ ๊ฒฝ์ฐ ์์ธ์ ์ผ๋ก new ํค์๋ ์์ด ๋ฆฌํฐ๋๋ก ์์ฑํ ์ ๋ ์๋๋ฐ, ์ด๋ฅผ ๋ฌธ์์ด ๋ฆฌํฐ๋ ์์ฑ ๋ฐฉ์์ด๋ผ๊ณ ํ๊ณ new ํค์๋๋ฅผ ์ฌ์ฉํ ๊ฒ๊ณผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌ ์ฅ์๊ฐ ๋ฌ๋ผ์ง๋ค.
// ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ง์ฐฌ๊ฐ์ง๋ก Heap ์์ญ์ ํ ๋น๋๋ค.
String str1 = new String("madplay");
// ์คํธ๋ง ์์๊ฐ์ผ๋ก ๊ด๋ฆฌ๋๋ค. String Constant Pool ์ด๋ผ๋ ์์ญ์ ์ ์ฅ๋๋ค.
String str2 = "madplay";
String str3 = "madplay"; // ๊ธฐ์กด "madplay" ์์ ์ฌํ์ฉ. str 2์ด๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ
String str4 = new String("madplay"); // ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑ. str1์ด๋ ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ
์ฐธ๊ณ ๋ก String Constant Pool์ ๊ธฐ์กด์๋ ์์๊ฐ ์ ์ฉ ๋ฉ๋ชจ๋ฆฌ์ (Perm ์์ญ) ๋ฐ๋ก ์ ์ฅ๋์ด์ก๋๋ฐ, ๋ฐํ์์ค ๋ฉ๋ชจ๋ฆฌ ์ฆ๊ฐ๋ก ์ธํ OutOfMemory ์์ธ๋ฅผ ๋ฐ์์ํฌ ์ ์์ด Java7 ์ดํ๋ก๋ ๊ฐ์ฒด์ ํจ๊ป Heap ๋ฉ๋ชจ๋ฆฌ์์ญ์์ ๊ด๋ฆฌํ๊ณ ์๋ค.
# ๋ฌธ์์ด ์กฐ์์ StringBuilder๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ด์
์์ 2๊ฐ์ง ํน์ง ๋๋ถ์ ์์ ์คํธ๋ง ๋ง์ ( "Hello" + "Hi" ) ์ ๊ฒฝ์ฐ ์ฑ๋ฅ์ด ์๋นํ ๊ตฌ๋ฆฌ๋ค.
- ์คํธ๋ง์ด ์์๊ฐ์ธ ๊ฒฝ์ฐ ๊ฐ์ฒด๋ฅผ ์์ ํ ์ ์๋ค. ํ๋ ค๋ฉด ์์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
- ๋ง์ ์ ํผ์ฐ์ฐ์ ("Hello", "Hi")์ ๊ฒฝ์ฐ ๋ฌธ์์ด ์ฒ๋ฆฌ ํ ์ธ๋ชจ์์ด์ง๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ํ์ง๋ง ์คํธ๋ง์ ์์์ฌ๋ถ์ ์๊ด์์ด Java8 ์ดํ Heap์์ญ์์ ๊ด๋ฆฌ๋๋ค. ์ฆ JVM GC์ ์ผ๊ฑฐ๋ฆฌ๊ฐ ๋์ด๋๋ค.
๊ทธ๋์ ๋๊ท๋ชจ๋ก ๋ฌธ์์ด ์กฐ์์ ํ ๋์๋ StringBuilder๋ฅผ ์ฌ์ฉํด์ผ ์ฑ๋ฅ ํ๋ฝ์ด ์๋ค. ๋ ์์ธํ ๊ฑด StringBuffer์ StringBuilder๋ฅผ ๋ค๋ฃฐ ๋ ์ค๋ช ํ๋๋ก ํ๊ฒ ๋ค.
# Constant Pool ์ด๋?
๋ฐํ์์ ์์ฑ๋๋ Static ์์ ์ ์ฅ์์ด๋ค. Constant Pool ๊ฐ์ฒด์ ์ ์ฅ๋๋ฉฐ ์๋์ ๊ฐ์ ์์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๋ค.
์ฐธ๊ณ ๋ก ์์ ํ์ Method Area, ์ฆ ์ ์ ์์ญ์ ์๋ ๋ฉ๋ชจ๋ฆฌ์ด๊ธฐ์ GC์ ๋์์ด ์๋๋ค.
// ์์ ํ์ ์ ์ฅ๋๋ ์์ ๊ฐ์ฒด
cp_info {
u1 tag; // ํ๊ทธ
u1 info[]; // ๊ฐ
}
/* tag๋ 1๋ฐ์ดํธ ์ซ์๋ก ๊ตฌ์ฑ๋๋ฉฐ JVM์๊ฒ ์๋์ ๊ฐ์ ํ์
์ ์ ๊ณตํฉ๋๋ค.
Utf8: 1
Integer: 3 (* Boolean, Short, Byte๋ ์ฌ๊ธฐ์ ํด๋น๋จ)
Float: 4
Long: 5
Double: 6
Class reference: 7
String reference: 8
*/
์ฌ๋ฏธ์๋ ์ฌ์ค์ Primarity Type ๋ฟ๋ง ์๋๋ผ String ๊ฐ์ฒด, ๋ ํผ๋ฐ์ค ํ์ ์ด ๊ฐ์ง ์ฃผ์ ๊ฐ๋ ์์ ํ๋ก ๊ด๋ฆฌ๋๋ค๋ ๊ฒ. ๋ค์๊ณผ ๊ฐ์ ์๋ฐํด๋์ค๋ฅผ ๋ง๋ค๊ณ ๋์ด์ ๋ธ๋ฌ ๋ช ๋ น์ธ javap -v ์ด๋ฆ.class ๋ฅผ ํตํด ๋ฐ์ดํธ์ฝ๋๋ฅผ ๋ถ์ํด๋ณด์.
public class ConstantPool { // class ์ด๋ฆ์ ConstantPool์ด๋ผ๊ณ ์ง์์ต๋๋ค.
public void sayHello() {
System.out.println("Hello World");
}
}
์ฐธ๊ณ ๋ก [ #n ] ์ ์์ํ์ n๋ฒ ์ธ๋ฑ์ค์ ์ ๊ทผํ๋ ๋ฐ์ดํธ์ฝ๋์ด๋ค.
[ #2 = ์์ํ์ ์์๊ฐ ]์ผ๋ก ์์ํ์ ํน์ ์ธ๋ฑ์ค์ ์์ ๊ฐ์ ๋ฑ๋ก ํ ์ ์๋ค.
// ์์์ ๋ง๋ ConstantPool.java์ ๋ฐ์ดํธ์ฝ๋.
#1 = Methodref #6.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #17 // Hello World
#4 = Methodref #18.#19 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #20 // com/baeldung/jvm/ConstantPool
#6 = Class #21 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 sayHello
#12 = Utf8 SourceFile
#13 = Utf8 ConstantPool.java
#14 = NameAndType #7:#8 // "<init>":()V
#15 = Class #22 // java/lang/System
#16 = NameAndType #23:#24 // out:Ljava/io/PrintStream;
#17 = Utf8 Hello World
#18 = Class #25 // java/io/PrintStream
#19 = NameAndType #26:#27 // println:(Ljava/lang/String;)V
#20 = Utf8 com/baeldung/jvm/ConstantPool
#21 = Utf8 java/lang/Object
#22 = Utf8 java/lang/System
#23 = Utf8 out
#24 = Utf8 Ljava/io/PrintStream;
#25 = Utf8 java/io/PrintStream
#26 = Utf8 println
#27 = Utf8 (Ljava/lang/String;)V
์ข ๋ ์์ธํ๊ฒ ์ค๋ช ํ๋ฉด ์๋์ ๊ฐ๋ค.
// [UTF8 ํ์
] sayHello()๋ฉ์๋์ (์
๋ ฅ)๋ฆฌํด ํ์
์ ์์ ํ์ ์ ์ฅ. void๋ V๋ก ํ์๊ฐ๋ฅ
#8 = Utf8 ()V
// [UTF8 ํ์
] ๋ฌธ์์ด "Hello World"์ ์ฌ๋ณผ์ Hello World๋ฅผ ์ง์ ํ๊ณ ์ด๋ฅผ ์์ ํ์ ์ ์ฅ .
#17 = Utf8 Hello World
// [Class ํ์
] System.out ํด๋์ค ๋ ํผ๋ฐ์ค๋ฅผ 25๋ฒ ์์๋ก ์์ํ์ ์ ์ฅ
#18 = Class #25 // java/io/PrintStream
// [NameAndType ํ์
] .println์ Name์ 26๋ฒ์์, Type์ 27๋ฒ ์์๋ก ์ ์ฅ.
#19 = NameAndType #26:#27 // println:(Ljava/lang/String;)V
// [UTF8 ํ์
] ๋ด๊ฐ ๋ง๋ ํด๋์ค์ ์ ๊ท์ด๋ฆ์ ์ ์ฅ (fully-qualified class name)
#20 = Utf8 com/baeldung/jvm/ConstantPool
์์ํ์์ ์ ๊ณตํ๋ ํ์ ์ ์ข ๋ฅ
์์ํ์ ํ์ ์ ์ค๋ช ํ๋ ์๋ฌธ
String ์์์ ์ ํํ ๋์์ ๋ชจ๋ฅด์ง๋ง, 16๋นํธ ์์ ๋ฌธ์์ด์ ํตํด ์์ํ ๋ด๋ถ์์๋ ์ค์ ๋ฐ์ดํธ๊ฐ์ ๊ฐ๋ฅดํจ๋ค๊ณ ํฉ๋๋ค. ์๋ง ์กฐ๋ฆฝ์์ผ๋ก ์ฌ์ฉํ๋ ๋ฏ ํ๋ฐ.. ๋๋ฌด ๊น์ ๋ด์ฉ์ด๋ ๋์ค์ ๋ฐ๋ก ๊ณต๋ถํ ์์ ์
๋๋ค.
- Integer, Float: 32๋นํธ ์์ (Boolean, Short, Byte ์์๋ Integer ์ทจ๊ธ)
- Double, Long: 64๋นํธ ์์
- String: a 16-bit string constant that points at another entry in the pool which contains the actual bytes
- Class: ์ ๊ทํ๋ ํด๋์ค ์ด๋ฆ(fully qualified class name)
- Utf8: ๋ฐ์ดํธ ๋ฌธ์์ด(a stream of bytes)
- NameAndType: (์ด๋ฆ . ํ์ ) ์ผ๋ก ํ์. ๋ณดํต ๋ค๋ฅธ ์์(#13.#15)๋ฅผ ์ด์ฉํ์ฌ ์ด๋ฆ๊ณผ ํ์ ์ ์ง์
- Fieldref, Methodref, InterfaceMethodref: (Class:NameAndType) ์ผ๋ก ํ์. Class์ NameAndType์ ์์์ ์ค๋ช ํ ์์ํ์์ ์ฌ์ฉ๋๋ ํ์ ์ ์๋ฏธํจ.
# Java7 -> Java8์์์ ๋ณ๊ฒฝ์
๊ธฐ์กด์ ์๋ฐ๋ ์์ ํ์ Permanent๋ผ๋ ์ ์ ์์ญ์์ ๊ด๋ฆฌํ์์ต๋๋ค. ํ์ง๋ง Static ์์ญ์ ํ ๋น ๋ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋๋ฆด์๊ฐ ์์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๋ฒ๊ฑฐ๋ฌ์ ๊ณ ์์๊ฐ ์ถ๊ฐ๋๋ค๋ณด๋ฉด StackOverFlow๊ฐ ๋ฐ์ํ ์ฌ์ง๊ฐ ์์ด ๊ฒฐ๊ตญ Java8์์ Heap ์์ญ์ผ๋ก ์ ํํ๊ฒ ๋ฉ๋๋ค.
์ฐธ๊ณ ๋ก Heap์ฒ๋ผ OS Level์์ ์ ๋์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋น๋ฐ๋ ์์ญ์ Native Memory ๋ผ๊ณ ๋ ๋ถ๋ฆ ๋๋ค. ์ฐธ๊ณ ๋ก JVM ์ต์ ์ ์ด์ฉํ์ฌ Perm(Java7), MetaSpace(Java8)์ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ ์์คํ ๋ณ๋ก ํ๋ํ ์ ์์ต๋๋ค.
'๐๊ธฐ๋ณธ ์ง์ > Java ๊ธฐ๋ณธ์ง์' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
StringBuffer์ StringBulider (0) | 2021.07.27 |
---|---|
์ฐ๋ ๋ ๋๊ธฐํ (sync, volatile, AtomicClass) (0) | 2021.07.27 |
.equals์ .hashCode()๋ ํญ์ ํจ๊ป ์ค๋ฒ๋ผ์ด๋ฉํด์ผํ๋ค. (0) | 2021.07.27 |
์ ๋ค๋ฆญ(Generic)์ ๋ํ์ฌ (0) | 2021.07.26 |
์๋ฐ์์ Stack Memory & Heap Memory (0) | 2021.07.10 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev