-
참조타입,메모리,배열복사언어/JAVA 2023. 7. 6. 14:06
1. 데이터 타입의 분류
데이터는 기본타입과 참조타입이 있다.
- 변수와 연결된 메모리셀에 무엇이 저장되느냐의 차이
- 변수의 복사는 메모리셀의 값을 기준으로 발생한다. ( 값이 복사되거나, 주소가 복사됨)
2. 자바 메모리 사용영역
jvm이 구동되면, jvm은 운영체제에서 할당받은 메모리 영역을 다음과 같이 구분해서 사용한다.
- 자바 컴파일러 javac가 자바 소스코드(.java)를 바이트코드(.class)로 컴파일
- Class Loader를 통해 JVM Runtime Data Area(메모리)에 로딩된다.
- Runtim Data Area에 로딩된 .class 들은 Executuion Engine이 해석 (바이트 코드 해석 (인터프리터, jit)
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치 (메소드영역, 스택영역, 힙영역)
이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어진다.
(마지막 과정은 코드 해석을 넘어 runtime에서 객체 생성, 소멸, 함수 호출 등등을 관장할 듯)
(* 컴파일과 코드의 실행은 따로 발생함 -> ide에 의해 한번에 작동하는 것 같지만 아님!!)
런타임 데이터 영역은 JVM의 메모리 영역 - 자바 애플리케이션 실행시 사용되는 데이터 적재
- 모든 스레드가 공유하는 공간
> 힙 : 클래스 인스턴스가 생성되어 저장되는 공간 (new 키워드로 생성된 객체와 배열 저장 - GC가 주기적으로 접근)
객체의 번지는 메서드 영역과 스택영역의 상수와 변수에서 참조 가능
> 메서드 영역 (데이터 영역) :
바이트코드 파일을 읽은 내용이 저장됨(runtime에서 바뀌는게 아니라, 그냥 첫 적재시)
클래스별로 상수(final), 정적필드(static 변수, static 메서드), 메소드 코드, 생성자 코드 저장
- 스레드(Thread)마다 하나씩 생성
- 스택영역 : 스택 영역은 함수의 호출과 관계되는 지역 변수와 매개변수가 저장되는 영역이다.
스택 영역은 함수의 호출과 함께 할당되며 함수의 호출이 완료되면 소멸한다.
함수가 호출되면, 스택에는 함수의 매개변수, 호출이 끝난 뒤 돌아갈 반환 주소값, 함수에서 선언된 지역변수 등이 저장되는데 스택 영역에 차례되로 저장되는 함수의 호출 정보를 스택 프레임이라한다.
- PC 레지스터 : 스레드 생성시 마다 생성되는 영역, 현재 실행되는 스레드의 부분 주소와 명령 저장
- 네이티브 메서드 스택 : 자바 이외 네이티브 코드 실행시 작동
참조변수로 객체를 참조하는 것은
스택 영역에 변수에 힙영역에 있는 객체 주소 받아다두는 것
다차원 배열일 경우
int[2][1] names = new int[2][1]; //names는 스택영역 int[0] int[1] 힙영역에서 int[0][0] int[1][0]에 해당하는 주소 담고 있음 //힙영역에서 인스턴스 멤버들 중 참조변수들은 힙영역에서 메모리셀에 힙영역의 주소를 가지고 있음
* 어디 영역에 있는지는 변수나 그런게 중요한게 아니라, 지역변수냐 정적 멤버냐 인스턴스 멤버냐 등등의 차이
* 자바에서 객체를 제거하는 유일한 방법은 객체의 모든 참조를 없애는 것 뿐이다!
3. 문자열 타입
- 문자열도 하나의 객체 String
문자열의 특징은 리터럴로 참조변수를 초기화하는 것과 new 로 초기화 하는 게 다르다.
String a ="a"; String b ="a"; //같은주소 String a = new String("a"); String b = new String("b); //다른주소
4. 배열의 복사
Object클래스에 Object clone() 객체 자신의 복사본을 반환하는 메서드를 사용해보자
- 단순히 인스턴스 변수의 값만 복사하므로, 참조타입 인스턴스 변수가 있으면, 깊은복사x (값은 같고 다른 객체_
복제된 인스턴스도 같은 배열의 주소를 갖기 때문에 복제된 인스턴스의 작업이 원래 인스턴스 영향 미침
깊은 복사를 하려면, clone메서드를 오버라이딩해라!
Cloneable 인터페이스
- clone를 호출하려면, 호출하는 클래스는 위 인터페이스를 구현해야함 (구현x하고 호출시 에러)
class A implements Cloneable{ int x,y; A(int x, int y){ this.x = x; this.y =y; } public Object clone(){ Object obj = null; try{ obj = super.clone(); }catch(CloneNotSuppoertedException e){} } }
* 접근제어자를 protected에서 public으로 수정해야함 -> 상속관계 없는 다른 클래스에서 clone() 호출 할 수 있음
* 인터페이스 구현된 클래스만 clone() 호출이 가능한 이유는 클래스에 인스턴스 보호하려고 그런다.
- 공변반환타입
jdk1.5부터 추가됨
메서드 오버라이딩 시에 조상 메서드의 반환타입을 자손 클래스의 타입으로 변경 가능하도록 한 것
원래 오버라이딩시에는 조상 메서드에 선언된 반환타입을 무조건 사용했어야하는데 -> 자손 클래스로 반환하는 것 허용
(오버라이딩은 원래 반환타입, 메서드이름, 매개변수가 동일해야함 -> 구현 내용만 달라야함)
(오버로딩은 같은 이름의 메서드를 아예 다르게 사용하는 것 매개변수가 아예 달라야함)
-깊은복사
class A implements Cloneable{ int x,y; SomeClass a; SomeClass b; A(int x, int y, SomeClass a, SomeClass b){ this.x = x; this.y =y; this.a = a; this.b =b; } public A clone(){ // 공변 반환타입 Object obj = null; try{ obj = super.clone(); //얕은복사 후에 }catch(CloneNotSuppoertedException e){} A newa = (A)obj; newa.a = new SomeClass(this.a.x, this.a.y); //인스턴스 멤버의 값들을 가지고 newa.b = new SomeClass(this.b.x,this.b.y); //새로운 인스턴스멤버 초기화 //참조변수들 새롭게 다 new로 초기화한다음에 내보내면됨 return newa; //반환 } }
'언어 > JAVA' 카테고리의 다른 글
상속,동적생성 (0) 2023.07.06 클래스,인스턴스 메서드 메모리 저장,싱글톤,접근제한자 (0) 2023.07.06 인터페이스 (0) 2023.07.06 람다식 (0) 2023.07.05 객체지향 - 캡슐화 (0) 2023.06.12