JAVA 프로그램의 메모리 분배에 대하여

목차

1. Java 프로그램 실행시 메모리 설명

2.JVM 메모리 분할

3.Java의 데이터 유형

4.Java의 문자열

5. HelloWorld와 결합하여 Java 프로그램의 메모리 분포를 분석합니다.


1. Java 프로그램 실행시 메모리 설명

          작성된 .java 프로그램 파일은 java 컴파일러 javac에 의해 .class 파일로 변환된 후 jvm(java라는 실행 프로그램)을 통해 .class 파일이 로드되어 실행됩니다. Java 프로그램이 실행될 때마다 Java 인스턴스(JVM)가 생성됩니다. Java 프로세스는 하나 이상의 스레드를 포함할 수 있는 JVM 인스턴스에 해당합니다. 각 JVM 인스턴스에는 해당 힙이 있고 각 스레드에는 자체 전용 스택이 있습니다. 프로세스에서 생성된 모든 클래스의 해당 배열은 힙에 저장되고 프로세스의 모든 스레드에서 공유됩니다. Java에서 힙의 개체에 메모리를 할당하면 이 개체의 변수가 초기화됩니다. 힙에 있는 객체에 대한 참조는 스택에 할당됩니다. 객체를 생성하려면 힙과 스택 모두에 메모리가 할당됩니다. 힙에 할당된 메모리는 객체 자체를 저장하는 반면, 스택에 할당된 메모리는 객체에 대한 참조만 저장합니다. 힙 객체. 함수 스택 프레임에 지역 변수가 새로 추가되면 스택 공간과 힙 공간에 공간이 할당되며, 지역 변수의 수명 주기가 끝나면 스택 공간은 즉시 재활용되고 힙 공간 영역은 GC 재활용을 기다립니다.

2.JVM 메모리 분할

JVM의 메모리는 힙, 스택 및 메소드 영역(메서드, 정적 영역이라고도 함)의 세 가지 영역으로 나눌 수 있습니다.

힙 영역: 
(1) 모든 객체가 저장되고 각 객체에는 해당 클래스에 대한 정보가 포함됩니다(클래스의 목적은 작업 명령을 얻는 것입니다). (2)
JVM에는 하나의 힙 영역(힙)만 있고 다음이 소유합니다. 스레드 공유, 기본 유형 및 개체 참조는 힙에 저장되지 않으며 개체 자체와 배열 자체만 저장됩니다.

스택 영역: 
(1) 각 스레드에는 스택 영역이 포함되어 있으며 기본 데이터 유형 자체와 사용자 정의 개체에 대한 참조만 스택에 저장됩니다. (2)
각 스택의 데이터(원본 유형 및 개체 참조)는 비공개입니다.
(3) 스택은 기본 유형 변수 영역, 실행 환경 컨텍스트, 작업 명령 영역(저장 작업 명령)의 세 부분으로 나뉩니다 .

메소드 영역(정적 영역): 
(1) 모든 스레드가 공유하는 메소드 영역에는 모든 클래스가 포함됩니다. (클래스는 클래스의 원래 코드를 나타냅니다. 클래스의 객체를 생성하려면 먼저 클래스의 코드를 로드해야 합니다. 메소드 영역 및 초기화됨) 및 정적 변수. 
(2) 메소드 영역에는 클래스 및 정적 변수와 같이 전체 프로그램에서 항상 고유한 요소가 포함됩니다. 
힙과 스택의 차이점:
(1) 스택과 힙은 모두 Java에서 데이터를 저장하는 데 사용되는 장소입니다. C++와 달리 Java는 스택과 힙을 자동으로 관리하므로 프로그래머가 스택이나 힙을 직접 설정할 수 없습니다. 
(2) 스택의 장점은 CPU에 직접 위치한 레지스터 다음으로 액세스 속도가 힙보다 빠르다는 것입니다. 하지만 스택에 저장되는 데이터의 크기와 수명을 결정해야 하고 유연성이 부족하다는 점이 단점이다.
힙의 장점은 메모리 크기를 동적으로 할당할 수 있다는 점과 수명을 미리 컴파일러에 알릴 필요가 없다는 점, Java의 가비지 수집기가 더 이상 사용되지 않는 데이터를 자동으로 수집한다는 것입니다.
하지만 단점은 런타임 시 메모리를 동적으로 할당하기 때문에 접근 속도가 느리다는 점입니다.

3.Java의 데이터 유형

(1) 기본 유형(기본 유형)에는 int, short, long, byte, float, double, boolean, char 등 총 8가지 범주가 있습니다.
이러한 형태의 정의를 int a = 3, long b = 255L 과 같은 형태로 정의하며 자동변수라 부른다. 자동 변수는 클래스의 인스턴스가 아닌 리터럴 값을 저장합니다.
즉, 클래스에 대한 참조가 아닙니다. 여기에는 클래스가 없습니다. 예를 들어 int a = 3; 여기서 a는 int 유형을 가리키는 참조로 리터럴 값 3을 가리킵니다.
이러한 리터럴 값의 데이터는 크기와 수명이 알려져 있으므로(이러한 리터럴 값은 특정 프로그램 블록에서 고정적으로 정의되며, 프로그램 블록이 종료된 후에는 필드 값이 사라짐) 속도를 위해, 스택에 존재합니다. . 
(2) Integer, String, Double 및 해당 기본 데이터 유형을 래핑하는 기타 클래스와 같은 패키징 클래스 데이터.
이러한 종류의 데이터는 모두 힙에 존재하는데, 자바는 new() 문을 사용하여 런타임 시 필요에 따라 동적으로 생성된다는 점을 컴파일러에 명시적으로 알려주므로 유연성이 더 뛰어나지만 시간이 더 많이 걸린다는 단점이 있습니다. 
(3) new() 문을 사용하여 사용자 정의 데이터 유형을
생성하고, 객체는 힙 영역에 저장되고 스택 영역의 참조를 통해 사용됩니다.

4.Java의 문자열

(1) 스택의 공유 특성
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
설명:
1) 컴파일러가 먼저 String str1 = "를 처리합니다. abc" ; 스택에 변수 str1에 대한 참조를 생성한 다음 스택에 abc 값이 있는지 검색합니다. 값이 없으면 abc를 저장한 다음 str1에서 abc를 가리킵니다.
2) 그런 다음 String str2 = "abc"를 처리합니다. b의 참조 변수를 생성한 후 abc 값이 스택에 이미 존재하므로 str2는 abc를 직접 가리킵니다. 이런 식으로 str1과 str2가 동시에 abc를 가리키는 상황이 발생합니다.
따라서 String str = "abc";와 같은 형식을 사용하여 클래스를 정의할 때 우리는 항상 String 클래스의 객체 str이 생성되는 것을 당연하게 여깁니다. 실제로 객체가 생성(스택에 생성)되지 않고 이전에 생성된 객체를 가리킬 수도 있습니다.
(2) 힙 메모리
new() 메소드는 매번 새로운 객체가 생성되도록 보장할 수 있습니다. 힙에 저장됩니다.
String 클래스의 불변성 특성으로 인해 String 변수의 값을 자주 변경해야 하는 경우 StringBuffer 클래스를 사용하여 프로그램 효율성을 높이는 것을 고려해야 합니다 .

5. HelloWorld와 결합하여 Java 프로그램의 메모리 분포를 분석합니다.

HelloWorld.java

//import java.lang.Integer;

public class HelloWorld {  //运行时jvm 把HelloWorld的代码全部都放入方法区     
    public static void main(String[] args) {  //main方法放在方法区
        System.out.println("Hello World!");
		Student stu = new Student(110, "Andy", 18);  //stu在栈上,引用堆上new出来的对象,new Student(110, "Andy", 18)在堆上存储
		stu.printStudent();
		int[] iArr = new int[10]; //iArr在栈上,引用堆上new出来的对象,new int[10]在堆上存储
		for (int i = 0; i < 10; i++) {
			iArr[i] = i;
		}
		System.out.println("iArr: " + iArr);
		int[] iArr1 = {12, 34, 45, 60, 45, 82};
		System.out.println("iArr: " + iArr1);
    }
}

class Student { //运行时jvm 把Student的代码全部都放入方法区   
private int id;
private String name;
private Integer age;   
    
public Student(int id, String name, Integer age) {     
	this.id = id;
	this.name = name;
	this.age = age;
}     
   
   
public void  printStudent() { //printStudent方法放在方法区
	System.out.println("id: " + id); 
	System.out.println("name: " + name); 
	System.out.println("age: " + age); 
}  
   
}

컴파일하고 실행합니다:

바이트코드 디컴파일:

javap -v HelloWorld.class

  비고: 오류 [오류: 매핑할 수 없는 문자 인코딩 GBK] 해결 방법

오류 원인: Windows의 기본 문자 집합은 GBK입니다. Java 파일의 중국어 문자가 GBK 문자 집합에 없으면 javac는 컴파일 시 오류를 보고합니다.

해결책:

(1) javac는 파일 인코딩 방법을 지정합니다. 예를 들어

javac -인코딩 UTF-8 HelloWorld.java

(2) 파일 인코딩을 GBK 인코딩으로 설정

Supongo que te gusta

Origin blog.csdn.net/hsy12342611/article/details/132514800
Recomendado
Clasificación