🍎 Backend/JAVA

[JAVA] 메모리 관리 & call by value

밈98 2023. 12. 8. 15:28
JVM의 자바 메모리 관리

JVM

  • JVM은 컴퓨터가 자바 프로그램을 실행하는 데 사용되는 가상 머신이다.
  • JVM은 메모리 관리를 자동으로 처리하여 자바 애플리케이션의 성능을 최적화한다.
  • 메모리 관리는 Xms와 Xmx라는 JVM 옵션을 사용한다.
    • JVM 메모리 구조
      • Heap 메모리
        • 모든 자바 클래스, 인스턴스와 배열이 할당되는 메모리 = 런타임 데이터 영역
        • Heap의 최초 크기 -Xms VM옵션으로 정의
        • 최대 Heap크기 -Xmx 옵션으로 설정 ( 기본적으로 최대 Heap크기는 64MB로 설정 )
        • Heap은 가비지컬텍터 전략에 따라 고정된 크기, 동적크기가 가능
      • Non-Heap 메모리
        • JVM 시작할 때 생성되며 클래스당 구조체(런타임 상수풀, 필드, 함수 데이터, 함수와 생성자 코드, 고정 문자열과 같은 것)를 저장
        • -XX:MaxPermSize VM 옵션으로 변경
      • Other 메모리
        • JVM 코드 자체, JVM 내부 구조체, 로딩된 프로파일러 에이전트 코드, 데이터 등을 저장

자바의 데이터형

  • 기본형(primitive type) : Boolean Type(boolean), Numeric Type(short, int, long, float, double, char)
  • 참조형(reference type) : Class Type, Interface Type, Array Type, Enum Type, 기본형을 제외한 모든 것들
  • 기본형 (int, double, boolean 등)은 stack의 변수 안에 value 저장
  • 참조형 (Integer, Obejct, Array, Map 등) 은 stakc의 변수 값에는 객체의 주소 값, 객체는 별도의 Heap영역에 저장

 

Call by Value & Call by Reference

Call by Value는 함수의 인자를 전달할 때 값을 전달하는 방식
Call by Reference는 주소를 전달하는 방식

Call by Value

  • 메소드를 호출할 때 넘겨 주고 싶은 인자를 지정하면, 메소드의 매개 변수가 지정한 변수 값의 복사본으로 초기화되는 것이다.
  • 따라서 함수 내에서의 변경은 메소드를 호출할 때 지정한 변수(원본)에 아무 영향을 미치지 않는다.
  • 자바는 Call by value방식을 사용한다!

Call by Reference

  • 메소드를 호출할 때 넘겨 주고 싶은 인자를 지정하면, 메소드의 매개 변수가 지정한 변수의 레퍼런스로 초기화되는 것이다.
  • 따라서 함수 내에서의 변경은 메소드를 호출할 때 지정한 변수(원본)에 영향을 미친다.

 

method1에선 a=10, b=5의 값을 전달했고 method2에선 이 값을 a=20, b=10으로 바꿔서 사용

method2를 마치고 돌아왔을 때 method1에서는 a=10, b=5 이 결과로 나온다.

=> call by value를 사용했기 때문!

 

 

자바에서는 call by value를 사용할때, 넘겨받은 메소드에서 값을 복사하여 새로운 지역변수에 저장!

이 때 Method2는 Method1의 변수를 사용한 것이 아니라, 자신이 새롭게 생성한 지역 변수Method1의 변수 이름과 변수 값을 복사하여 사용하는 것

 

만일 call by reference방식을 사용했다면 a,b의 값에 영향을 미친다

 

예외 경우

public class JavaIsCallByValue {

    public static void main(String[] args) {

        Num numA = new Num(1);
        Num numB = new Num(3);
        System.out.println("swap 전 numA:" + numA.num + " " + "numB:" + numB.num);
        swap(numA, numB);
        System.out.println("swap 후 numA:" + numA.num + " " + "numB:" + numB.num);
    }

    private static void swap(Num numX, Num numY) {
        Num tmp = numX;
        numX = numY;
        numY = tmp;
    }

    public static class Num {
        int num;

        public Num(int num) {
            this.num = num;
        }
    }
}

 

public class JavaIsCallByValue {

    public static void main(String[] args) {

        Num numA = new Num(1);
        Num numB = new Num(3);
        System.out.println("swap 전 numA:" + numA.num + " " + "numB:" + numB.num);
        swap(numA, numB);
        System.out.println("swap 후 numA:" + numA.num + " " + "numB:" + numB.num);
    }

    private static void swap(Num numX, Num numY) {
        int tmp = numX.num;
        numX.num = numY.num;
        numY.num = tmp;
    }

    public static class Num {
        int num;

        public Num(int num) {
            this.num = num;
        }
    }
}

값이 변경된 이유

  • 자바가 함수의 인자로 전달해주는 것은 복사된 참조 값을 전달하기 때문
  • 즉, 참조값을 받아서 그 참조값을 이용하는 것은 가능하기에 각각의 필드값이 변경

 

 

'🍎 Backend > JAVA' 카테고리의 다른 글

[java] abstract(추상) vs implements의 비교  (1) 2024.12.20
[JAVA] 해시 맵  (0) 2023.12.11
[Java] 컴파일 과정  (0) 2023.12.04
자바 기초  (0) 2023.03.02
[JAVA] 클래스와 객체  (0) 2023.02.05