자바의 힙과 스택 Java는 메모리를 두 가지 유형으로 나눕니다. 하나는 스택 메모리이고 다른 하나는 힙 메모리입니다.
객체의 함수 및 기준 변수로 정의 된 일부 기본 유형의 변수는 함수의 스택 메모리에 할당됩니다. 변수가 코드 블록에 정의되면 Java는 스택의 변수에 대한 메모리 공간을 할당합니다. 변수의 범위가 변수의 범위를 초과하면 Java는 변수에 할당 된 메모리 공간을 자동으로 해제하고 메모리 공간을 즉시 별도로 사용할 수 있습니다.
힙 메모리는 새로 생성 된 객체와 배열을 저장하는 데 사용됩니다. 힙에 할당 된 메모리는 Java Virtual Machine 자동 쓰레기 수집기에 의해 관리됩니다. 힙에 어레이 또는 객체가 생성 된 후 스택에서 특수 변수를 정의 할 수 있습니다. 이 변수의 값은 힙 메모리의 어레이 또는 객체의 첫 번째 주소와 같습니다. 스택 의이 특수 변수는 배열 또는 객체의 참조 변수가됩니다. 앞으로 프로그램의 스택 메모리에서 참조 변수를 사용하여 힙의 배열 또는 객체에 액세스 할 수 있습니다. 참조 변수는 배열 또는 객체의 별칭 또는 코드 이름과 동일합니다.
기준 변수는 일반 변수입니다. 정의되면 스택에 메모리가 할당됩니다. 참조 변수는 프로그램이 실행될 때 범위 밖에서 릴리스됩니다. 배열 및 객체 자체는 힙에 할당됩니다. 프로그램이 코드 블록 외부에서 실행 되더라도 배열 및 객체를 생성하기 위해 새로운 명령문이 배열되어 있으면 배열 및 객체 자체가 차지하는 힙 메모리가 해제되지 않습니다. 배열과 물체는 참조 변수가 없을 때만 쓰레기가되어 더 이상 사용할 수 없지만 여전히 메모리를 점유 할 수 없으며 불확실한 시간에 쓰레기 수집기에 의해 방출됩니다. 이것이 또한 Java가 더 많은 기억을 취하는 주된 이유입니다. 실제로, 스택의 변수는 힙 메모리의 변수를 가리 킵니다. 이는 Java의 포인터입니다!
자바에서 힙과 스택
Java는 메모리를 두 가지 유형으로 나눕니다. 하나는 스택 메모리이고 다른 하나는 힙 메모리입니다.
1. 스택과 힙은 모두 Java가 RAM에 데이터를 저장하는 데 사용되는 장소입니다. C ++와 달리 Java는 스택 및 힙을 자동으로 관리하며 프로그래머는 스택이나 힙을 직접 설정할 수 없습니다.
2. 스택의 장점은 액세스 속도가 힙보다 빠르며 CPU 직접 위치에있는 레지스터에 이어 두 번째는 더 빠릅니다. 그러나 단점은 스택의 데이터 크기와 수명이 결정적이어야하고 유연성이 부족하다는 것입니다. 또한 스택 데이터를 공유 할 수 있습니다. 힙의 장점은 메모리 크기를 동적으로 할당 할 수 있으며 수명을 미리 컴파일러에 알 필요가 없다는 것입니다. Java의 쓰레기 수집기는 더 이상 사용되지 않은 데이터를 자동으로 수집합니다. 그러나 단점은 런타임에 메모리가 동적으로 할당되어야하며 액세스 속도가 느리다는 것입니다.
3. Java에는 두 가지 유형의 데이터가 있습니다.
하나는 기본 유형 (원시 유형)이며 8 가지 유형, 즉 int, short, long, byte, float, double, boolean, char (참고, 참고,
기본 유형의 문자열은 없습니다). 이 유형의 정의는 int a = 3과 같은 양식으로 정의됩니다. 긴 b = 255l; 자동 변수라고합니다. 자동 변수에는 클래스의 인스턴스, 즉 클래스에 대한 언급이 아니라 문자 그럴 값이 포함되어 있으며 여기에는 클래스가 없습니다. 예를 들어, int a = 3; 여기 a는 int 유형을 가리키는 참조입니다.
문자 그대로의 값 3을 가리 킵니다.이 문자 값의 크기로 인해,이 문자 값의 수명은 알려질 수 있습니다 (이 문자 값은 프로그램 블록에서 고정으로 정의되고 프로그램 블록이 종료되면 필드 값이 사라집니다).
속도를 추구하기 위해 스택에 존재합니다.
또한 스택의 매우 중요한 특수 기능은 스택의 데이터를 공유 할 수 있다는 것입니다. 우리가 동시에 정의한다고 가정합니다.
int a = 3;
int b = 3;
컴파일러는 먼저 int a = 3을 처리합니다. 먼저 스택의 변수 A에 대한 참조를 작성한 다음 문자 그대로 값이 3 인 주소가 있는지 확인합니다. 찾을 수없는 경우 문자 그대로 값이 3 인 주소를 열고 3의 주소를 가리킨 다음 int b = 3; B의 기준 변수를 작성한 후, 스택에 이미 문자 그대로의 값이 있기 때문에 B는 3의 주소를 직접 가리 킵니다. 이러한 방식으로 A와 B는 동시에 3을 가리 킵니다.
이 문자 그대로 참조는 클래스 객체의 참조와 다르다는 점에 유의해야합니다. 두 클래스 객체의 참조가 동시에 객체를 가리킨다고 가정하면, 한 개체 기준 변수가 객체의 내부 상태를 변경하면 다른 객체 참조 변수는이 변경을 즉시 반영합니다. 대신, 문자 그대로 참조를 통해 그 값을 수정해도 다른 값이 그에 따라 변경되지 않습니다. 위의 예에서와 같이, 우리는 a와 b의 값을 정의한 후에, a = 4; 그런 다음 B는 4와 같거나 3과 같지 않습니다. 컴파일러 내부에서 A = 4가 발생하면 스택에 문자 그대로 값이 4인지 다시 검색합니다. 그렇지 않은 경우 주소를 다시 열어 4의 값을 저장하십시오. 이미 존재하는 경우이 주소를 직접 가리 킵니다. 따라서 값 A의 변화는 값에 영향을 미치지 않습니다. b.
다른 유형은 해당 기본 데이터 유형을 감싸는 정수, 문자열, 이중 등과 같은 클래스 데이터를 포장하는 것입니다. 이 모든 클래스 데이터는 힙에 존재합니다. Java는 새로운 () 문을 사용하여 컴파일러를 표시하고 런타임에 필요한만큼 동적으로 만 생성하므로 더 유연하지만 단점은 더 많은 시간이 걸린다는 것입니다.
Java에는 데이터를 저장할 수있는 6 개의 다른 장소가 있습니다.
1. 등록. 이것은 다른 스토리지 영역과는 다른 장소에 위치하기 때문에 가장 빠른 저장 영역입니다. 프로세서는 프로세서입니다. 그러나 레지스터 수는 매우 제한되어 있으므로 요구 사항에 따라 컴파일러가 레지스터를 할당합니다. 당신은 그것을 직접 제어 할 수 없으며 프로그램에 레지스터가 존재한다는 징후를 느낄 수 없습니다.
2. 스택. 범용 RAM에 위치하지만 "스택 포인터"를 사용하면 프로세서에서 지원할 수 있습니다. 스택 포인터가 아래로 이동하면 새 메모리가 할당됩니다. 그것이 올라가면 그 기억은 해제됩니다. 이것은 스토리지를 할당하는 빠르고 효율적인 방법이며, 등록에 이어 두 번째입니다. 프로그램을 만들 때 Java 컴파일러는 스택에 저장된 모든 데이터의 정확한 크기와 수명주기를 알아야합니다. 스택 포인터를 위아래로 이동하려면 해당 코드를 생성해야하기 때문입니다. 이 제약 조건은 프로그램의 유연성을 제한하므로 일부 JA VA 데이터는 스택에 저장되지만 특히 객체 참조가 있지만 Java 객체는 저장되지 않습니다.
3. 힙. 소위 Java 개체를 저장하기위한 범용 메모리 풀 (RAM에도 존재). 힙의 장점은 컴파일러가 힙에서 할당 할 저장 영역 수를 알 필요가 없으며, 저장된 데이터가 힙에서 얼마나 오래 지속될 것인지 알 필요가 없다는 것입니다. 따라서 힙에 스토리지를 할당하는 데 큰 유연성이 있습니다. 객체를 만들면 새로운 코드 라인 만 작성하면됩니다. 이 코드 라인을 실행할 때는 힙에 자동 저장 및 할당됩니다. 물론이 유연성을 위해 해당 코드를 지불해야합니다. 힙으로 스토리지를 스택으로 보관하는 것보다 스토리지를 할당하는 데 더 많은 시간이 걸립니다.
4. 정적 저장. "정적"여기서 "고정 된 위치에서"를 의미합니다. 정적 저장소는 프로그램이 실행될 때 항상 존재했던 데이터를 저장합니다. 키워드 정적을 사용하여 객체의 특정 요소가 정적이라는 것을 식별 할 수 있지만 Java 객체 자체는 정적 저장 공간에 저장되지 않습니다.
5. 일정한 저장. 상수 값은 일반적으로 프로그램 코드 내부에 직접 저장되며 변경되지 않기 때문에 안전합니다. 때로는 임베디드 시스템에서 상수 자체가 다른 부분과 분리되어 있으므로이 경우 ROM에 넣는 것이 선택 사항입니다.
6. 비 램 스토리지. 데이터가 프로그램 밖에서 완전히 생존하면 프로그램을 제어하지 않고 남겨질 수 있으며 프로그램이 실행되지 않을 때 존재할 수 있습니다.
속도 측면에서 다음과 같이 관계가 있습니다.
등록 <stack <heap <기타
"위의 구절은"자바의 생각 "에서 추출됩니다."
Question 1:
문자열 str1 = "abc"; 문자열 str2 = "abc"; System.out.println (str1 == str2); //진실
Question 2:
문자열 str1 = 새 문자열 ( "abc"); 문자열 str2 = 새 문자열 ( "abc"); System.out.println (str1 == str2); // 거짓
질문 3 :
문자열 s1 = "ja"; 문자열 s2 = "va"; 문자열 s3 = "Java"; 문자열 S4 = S1 + S2; System.out.println (s3 == S4); // false System.out.println (s3.equals (s4)); // true
객체의 함수 및 기준 변수에 정의 된 일부 기본 유형의 변수는 모두 함수의 스택 메모리에 할당됩니다.
변수가 코드 블록에 정의되면 Java는 스택 에서이 변수에 대해 메모리 공간을 할당합니다. 변수의 범위가 변수를 초과하면 Java는 변수에 할당 된 메모리 공간을 자동으로 해제하고 메모리 공간을 즉시 별도로 사용할 수 있습니다.
힙 메모리는 새로 생성 된 객체와 배열을 저장하는 데 사용됩니다.
힙에 할당 된 메모리는 Java Virtual Machine의 자동 쓰레기 수집기에 의해 관리됩니다.
힙에 배열 또는 객체가 생성 된 후 스택에서 특수 변수를 정의 할 수 있으므로 스택 의이 변수의 값은 힙 메모리의 배열 또는 객체의 첫 번째 주소와 동일하고 스택의 변수는 어레이 또는 객체의 참조 변수가됩니다.
참조 변수는 배열 또는 객체에 주어진 이름과 동일합니다. 프로그램의 스택의 참조 변수를 사용하여 힙의 어레이 또는 객체에 액세스 할 수 있습니다.
구체적으로 : 스택과 힙은 모두 Java가 RAM에 데이터를 저장하는 데 사용되는 장소입니다. C ++와 달리 Java는 스택 및 힙을 자동으로 관리하며 프로그래머는 스택이나 힙을 직접 설정할 수 없습니다.
Java 힙은 객체가 공간을 할당하는 런타임 데이터 영역입니다. 이 객체는 New, NewArray, anewarray 및 Multianewarray와 같은 지침을 통해 설정됩니다. 그들은 프로그램 코드를 명시 적으로 릴리스 할 필요가 없습니다. 힙은 쓰레기 수거를 담당합니다. 힙의 장점은 메모리 크기를 동적으로 할당 할 수 있다는 것입니다. 수명은 런타임에 메모리를 동적으로 할당하기 때문에 컴파일러에 미리 알릴 필요가 없다는 것입니다. Java의 쓰레기 수집기는 더 이상 사용되지 않은 데이터를 자동으로 수집합니다. 그러나 단점은 런타임에 메모리를 동적으로 할당해야하기 때문에 액세스 속도가 느리다는 것입니다.
스택의 장점은 액세스 속도가 힙보다 빠르고 레지스터에 이어 두 번째로 스택 데이터를 공유 할 수 있다는 것입니다. 그러나 단점은 스택의 데이터 크기와 수명이 결정적이어야하고 유연성이 부족하다는 것입니다. 스택은 주로 일부 기본 유형의 변수 (, int, short, long, byte, float, double, boolean, char) 및 객체 핸들을 저장합니다.
스택의 매우 중요한 특수 기능은 스택에 존재하는 데이터를 공유 할 수 있다는 것입니다. 우리가 동시에 정의한다고 가정합니다.
int a = 3;
int b = 3;
컴파일러는 먼저 int a = 3을 처리합니다. 먼저 변수 a로 스택에 참조를 생성 한 다음 스택에 3의 값이 있는지 확인합니다. 발견되지 않으면 3을 저장 한 다음 A에서 3에서 3을 가리킨 다음 int B = 3을 처리합니다. 스택에 이미 3의 값이 있기 때문에 B의 기준 변수를 생성 한 후 B는 직접 3으로 가리 킵니다. 이러한 방식으로 A와 B는 동시에 3을 가리 킵니다. 현재 A = 4가 다시 설정된 경우; 그런 다음 컴파일러가 스택에 4 값이 있는지 다시 검색합니다. 그렇지 않은 경우, 4와 지점을 저장하십시오. 이미 존재하는 경우이 주소를 직접 지적하십시오. 따라서 값 A의 변화는 값에 영향을 미치지 않습니다. b. 이 데이터 공유는 동시에 하나의 객체를 가리키는 두 객체의 참조 공유와 다릅니다.이 경우 A의 수정은 B에 영향을 미치지 않기 때문에 공간을 절약하는 데 도움이되는 컴파일러에 의해 수행되기 때문에이 데이터의 수정은 B에 영향을 미치지 않기 때문입니다. 객체 참조 변수는이 객체의 내부 상태를 수정하고 다른 객체 참조 변수에 영향을 미칩니다.
문자열은 특수 포장 데이터입니다. 사용할 수 있습니다 :
문자열 str = 새 문자열 ( "abc"); 문자열 str = "abc";
만들어야 할 두 가지 형식이 있습니다. 첫 번째는 새 ()를 사용하여 새 개체를 만드는 것입니다. 새 개체는 힙에 저장됩니다. 새 객체가 호출 될 때마다 생성됩니다.
두 번째 유형은 먼저 스택에서 문자열 클래스의 객체에 변수 str을 생성 한 다음 스택에 저장된 "ABC"가 있는지 확인하는 것입니다. 그렇지 않은 경우 스택에 "ABC"를 저장하고 Str가 "ABC"를 가리 키십시오. 이미 "ABC"가있는 경우 Str가 직접 "ABC"를 가리 키십시오.
클래스의 값이 동일인지 비교할 때 equals () 메소드를 사용하십시오. 두 래퍼 클래스의 참조가 동일한 객체를 가리키는 지 여부를 테스트 할 때 ==를 사용하고 아래의 이론을 설명하기 위해 아래 예제를 사용하십시오.
문자열 str1 = "abc"; 문자열 str2 = "abc"; System.out.println (str1 == str2); //진실
str1과 str2가 동일한 물체를 가리킨다는 것을 알 수 있습니다.
문자열 str1 = 새 문자열 ( "abc"); 문자열 str2 = 새 문자열 ( "abc"); System.out.println (str1 == str2); // 거짓
새로운 방법은 다른 객체를 생성하는 것입니다. 한 번에 하나씩 생성하십시오.
따라서, 두 번째 방식으로, 다중 "ABC"문자열이 생성되며 메모리에는 하나의 객체 만 있습니다. 이 글쓰기 방법은 유익하고 메모리 공간을 절약합니다. 동시에 JVM은 스택에서 데이터의 실제 상황을 기반으로 새 개체를 생성 해야하는지 자동으로 결정하기 때문에 프로그램의 실행 속도를 어느 정도 향상시킬 수 있습니다. 문자열 코드 str = new String ( "ABC");
반면에, 참고 : String str = "abc"와 같은 형식을 사용하여 클래스를 정의 할 때, 우리는 항상 String 클래스의 객체 str을 생성 할 수 있다고 당연한 것으로 여깁니다. (반드시 미리 없으면 사전에 만들어지기 때문에 그 것은 아닙니다. 이것은 객체의 생성입니다. 이미 있다면 원래 객체를 가리 키십시오)! 객체가 만들어지지 않았을 수도 있습니다! 그리고 아마도 이전에 만들어진 객체를 가리킬 수도 있습니다. 새로운 () 메소드를 통해서만 새 개체가 매번 생성되도록 할 수 있습니다. 문자열 클래스의 불변의 특성으로 인해 문자열 변수가 값을 자주 변환 해야하는 경우 StringBuffer 클래스를 사용하여 프로그램 효율성을 향상시키는 것을 고려해야합니다.