24-05-01 Kotlin 객체(인스턴스)가 생성, 저장, 호출되는 방식
오늘은 튜터님들의 강의 세션이 많은 하루였다. 오늘은 CS 지식 관련해서도 배운 점이 많아서 여러가지로 이해에 많은 도움이 되어 좋은 하루였다고 할 수 있겠다.
오늘은 객체(인스턴스)가 생성되고 호출될 때 어떻게 JVM의 메모리에 저장되고 불러와서 사용되는지에 대해 알게되었다. 그 내용을 간단하게 정리해본다.
1. 객체(인스턴스)가 생성, 저장, 호출되는 방식
객체(인스턴스)가 생성되고 호출될 때 어떤 방식으로 메모리에 저장되고 호출되는지에 대해 알아볼 수 있었다.
프로그램이 실행되면서 클래스가 인스턴스화가 되면 인스턴스의 데이터들은 힙(Heap) 영역에 저장되게 된다. 그리고 생성된 객체는 스택(Stack) 영역에 저장되게 되는데 이 때 스택 영역에는 생성된 인스턴스의 참조값(주소)만이 저장되게 된다.
그리고 메서드가 객체를 호출하게 되면 이 참조값(주소)을 복사하여 인자로 전달하게 된다. 그리고 이 참조가 가리키는 데이터를 변화시킬 수 있는 권한까지 전달이 되게 된다. 따라서 데이터가 메서드에 의해 값이 바뀌게 된다면 이 참조값(주소)이 가리키고 있는 데이터가 변하게 되고 그러면 객체의 참조값(주소)이 가리키고 있던 데이터 역시 바뀌게 된다.
너무 짧고 간단하게 적은게 아닌가 싶긴한데 내가 완전히 이해한 부분만 정리하려다보니 아주 짧아진 것 같다.
찾아보면 JVM의 메모리 사용 방식에 대해 자세한 그림과 함께 자세한 설명이 있는 양질의 글이 많이 찾을 수 있었다.
나중에 CS 지식에 대한 이해가 더 필요할 때 다시 한 번 정독하면 좋을 것 같다.
2. 문자열이 저장되는 독특한 방식
이전에 원시타입과 참조타입에 대해서 공부했을 때 다소 의아한 부분이 하나 있었다.
문자열은 원시타입이 아닌 참조타입이기 때문에 생성될 때 하나의 객체가 생성되는 것으로 알고 있었지만 서로 다른 변수에 같은 문자열을 대입연산자로 집어넣은 후 동일성을 비교하게 되면 동일하다는 결과가 나오는 것이다.
하지만 String 생성자를 이용해 문자열을 만들어 대입해주면 그것은 동일하지 않다고 결과가 나오는 것 역시 확인한 적이 있다.
fun main(){
val a = "가나다"
val b = "가나다"
val c = String(charArrayOf('가', '나', '다'))
println(a == b) // true
println(a == c) // true
// a와 b는 동일하지만, a와 c는 동일하지않다.
println(a === b) // true
println(a === c) // false
}
한동안 의문만 품고 있었는데 검색을 하다가 String Constant Pool이라는 것이 있다는 것을 알게 되었다.
변수를 선언하고 문자열을 대입해주게 되면 스택 영역에 객체가 생성되게 되고 값들은 힙 영역에 저장되게 된다. 이때 a = "가나다"와 같이 큰 따옴표 안에 값을 넣어 문자열을 만들게 되면 힙 영역 안에 있는 String Constant Pool이라는 영역에 저장되게 된다. 만약 이미 String Costant Pool에 같은 문자열이 있다면 문자열이 새로 저장되지 않고 변수에 같은 참조값(주소)를 저장하게 된다. 다시 말해 이미 큰 따옴 표로 문자열을 만들게 되면 한 번 저장한 문자열은 새로 힙 영역에 생성되지 않는다.
위에서 한 것과 같이 String 생성자를 이용하면 이 String Constant Pool 바깥에 문자열을 저장할 수 있다. 그렇기 때문에 위에 작성한 코드에서 a와 b는 가리키는 주소가 완전히 동일하기 때문에 === 으로 비교하면 true가 반환되고, a와 c는 값은 같지만, 가리키는 주소는 동일하지 않기 때문에 ==으로 비교하면 true가 ===으로 비교하면 false가 반환되는 것이다.
3. 오늘 배운 것
- 객체가 생성되고 저장되고 호출되는 방식에 대해 공부해보았다.
- ERD 작성법에 대해 조금 공부해보았다.
- 알고리즘을 어떻게 공부해야할지에 대해 알 수 있었다. 앞으로 더 열심히 해보아야겠다.