>Java >java지도 시간 >JVM 소개

JVM 소개

一个新手
一个新手원래의
2017-10-10 09:17:511916검색

JVM 소개

1. JVM이란?

JVM은 Java Virtual Machine의 약어입니다. JVM은 컴퓨팅 장치의 사양으로, 실제 컴퓨터에서 다양한 컴퓨터 기능을 시뮬레이션하여 구현하는 가상의 컴퓨터입니다. JVM(Java Virtual Machine)에는 바이트코드 명령어 세트, 레지스터 세트, 스택, 가비지 수집 힙 및 저장 방법 필드가 포함되어 있습니다. JVM은 특정 운영 체제 플랫폼과 관련된 정보를 보호하므로 Java 프로그램은 Java 가상 머신에서 실행되는 대상 코드(바이트코드)만 생성하면 되며, 수정 없이 다양한 플랫폼에서 실행될 수 있습니다. JVM이 바이트코드를 실행할 때 실제로는 궁극적으로 바이트코드를 특정 플랫폼에서 실행하기 위한 기계 명령어로 해석합니다.

Java 언어의 매우 중요한 특징은 플랫폼으로부터의 독립성입니다. 이 기능을 달성하려면 Java 가상 머신을 사용하는 것이 핵심입니다. 일반적인 고급 언어를 다른 플랫폼에서 실행하려면 최소한 다른 대상 코드로 컴파일해야 합니다. Java 언어 가상 머신이 도입된 이후에는 다른 플랫폼에서 실행될 때 Java 언어를 다시 컴파일할 필요가 없습니다. 자바 언어는 자바 가상 머신을 사용하여 특정 플랫폼과 관련된 정보를 보호하므로 자바 언어 컴파일러는 자바 가상 머신에서 실행되는 대상 코드(바이트코드)만 생성하면 되며 수정 없이 여러 플랫폼에서 실행될 수 있습니다. . JVM(Java Virtual Machine)은 바이트코드를 실행할 때 바이트코드를 특정 플랫폼에서 실행하기 위한 기계 명령어로 해석합니다. 이것이 바로 Java가 "한 번 컴파일하면 어디서나 실행"할 수 있는 이유입니다.

2. JRE/JDK/JVM은 어떤 관계인가요?

JRE(JavaRuntimeEnvironment, Java 런타임 환경)는 Java 플랫폼입니다. 모든 Java 프로그램은 JRE에서 실행되어야 합니다. 일반 사용자는 개발된 자바 프로그램을 실행하고 JRE를 설치하기만 하면 됩니다.

JDK(Java Development Kit)는 프로그램 개발자가 Java 프로그램을 컴파일하고 디버깅하는 데 사용하는 개발 도구 키트입니다. JDK 도구도 Java 프로그램이므로 실행하려면 JRE가 필요합니다. JDK의 독립성과 무결성을 유지하기 위해 JDK 설치 프로세스 중에 JRE도 설치의 일부입니다. 따라서 JDK 설치 디렉터리 아래에는 JRE 파일을 저장하는 데 사용되는 jre라는 디렉터리가 있습니다.

JVM(JavaVirtualMachine, Java Virtual Machine)은 JRE의 일부입니다. 컴퓨터의 다양한 기능을 실제 컴퓨터에 시뮬레이션하여 구현한 가상의 컴퓨터입니다. JVM에는 프로세서, 스택, 레지스터 등과 같은 자체적인 완전한 하드웨어 아키텍처가 있으며 해당 명령어 시스템도 있습니다. Java 언어의 가장 중요한 기능은 크로스 플랫폼 작동입니다. JVM을 사용하는 목적은 운영 체제 독립성을 지원하고 크로스 플랫폼을 구현하는 것입니다.

3. JVM 원리

JVM은 Java 컴파일러와 OS 플랫폼 사이의 가상 프로세서인 Java의 핵심이자 기초입니다. Java 바이트코드 프로그램이 실행될 수 있는 소프트웨어 방법을 사용하여 구현된 기본 운영 체제 및 하드웨어 플랫폼을 기반으로 하는 추상 컴퓨터입니다.

Java 컴파일러는 JVM을 지향하고 JVM이 이해할 수 있는 코드 또는 바이트코드 파일을 생성하기만 하면 됩니다. Java 소스 파일은 바이트코드 프로그램으로 컴파일되고, 각 명령어는 JVM을 통해 다양한 플랫폼용 기계어 코드로 변환되어 특정 플랫폼에서 실행됩니다.

4. JVM이 프로그램을 실행하는 과정

1) .class 파일 로드 2) 메모리 관리 및 할당 3) 가비지 컬렉션 수행

JRE(Java 런타임 환경) Java 프로그램의 실행 루프 구성 JVM에 의해 Java 프로그램이 실행되는 환경이기도 하지만 동시에 운영 체제의 애플리케이션이자 프로세스이기 때문에 자체적인 실행 라이프사이클과 자체 코드 및 데이터도 가지고 있습니다. 공간. JVM은 전체 jdk의 맨 아래에 있으며 운영체제의 상호작용을 담당하며 운영체제 환경을 보호하고 완전한 자바 실행 환경을 제공하는 역할을 하므로 가상 컴퓨터이기도 하다. jdk에서 Java.exe를 통해 운영체제 로딩이 완료됩니다. 1) JVM 로딩 환경 생성 및 구성 2) JVM.dll 로딩 3) JVM.dll을 초기화하고 JNIENV에 마운트합니다. ( JNI 호출 인터페이스) 인스턴스 4) JNIEnv 인스턴스를 호출하여 클래스 클래스를 로드하고 처리합니다.

5. JVM 수명 주기

1) JVM 인스턴스는 프로세스 수준에서 시작되는 독립적으로 실행되는 Java 프로그램에 해당합니다
a). Java 프로그램이 시작되면 JVM 인스턴스가 생성됩니다. public static void
main(String[] args) 함수가 있는 모든 클래스를 JVM 인스턴스
b) 실행을 위한 시작점으로 사용할 수 있습니다. main()은 프로그램의 초기 스레드에 대한 시작점 역할을 하며 다른 스레드는 이 스레드에 의해 시작됩니다. JVM 내부에는 데몬 스레드와 비데몬 스레드라는 두 종류의 스레드가 있습니다. main()은 비데몬 스레드에 속합니다. 데몬 스레드는 일반적으로 JVM 자체에서 사용됩니다. 생성된 것은 데몬 스레드입니다.
c) 죽음. 프로그램의 데몬이 아닌 스레드가 모두 종료되면 JVM이 종료됩니다. 보안 관리자가 허용하는 경우 프로그램은 Runtime 클래스 또는 System.exit()를 사용하여 종료할 수도 있습니다

2) JVM 실행 엔진 인스턴스는 사용자 실행 프로그램에 속한 스레드에 해당하며 스레드 수준

6. JVM 아키텍처

  • ClassLoader(.class 파일을 로드하는 데 사용)

  • 실행 엔진(바이트코드 실행 또는 로컬 메소드 실행)

  • 런타임 데이터 영역(메서드 영역, 힙, 자바 스택, PC 레지스터, 로컬 메소드 스택)

7 JVM 런타임 데이터 영역

첫 번째 블록: PC 레지스터

PC 레지스터는 각 스레드가 다음에 실행할 JVM 명령을 저장하는 데 사용됩니다. 메소드가 기본인 경우 PC 레지스터는 어떤 정보도 저장하지 않습니다.

두 번째 블록: JVM 스택

JVM 스택은 스레드 전용입니다. 각 스레드가 생성될 때 JVM 스택은 현재 스레드에 로컬 기본 유형 변수(Java에서 정의된 8개)를 저장합니다. 기본 유형: boolean, char, byte, short, int, long, float, double), 부분 반환 결과 및 기본이 아닌 유형의 객체는 JVM 스택의 힙을 가리키는 주소만 저장합니다.

세 번째 블록: Heap

JVM에서 객체 인스턴스와 배열 값을 저장하는 데 사용하는 영역입니다. Java에서 new를 통해 생성된 모든 객체의 메모리가 여기에 할당된다고 볼 수 있습니다. 힙은 GC가 회수될 때까지 메모리가 기다려야 합니다.

(1) 힙은 JVM의 모든 스레드에서 공유되므로 여기에 개체 메모리를 할당하려면 잠금이 필요하며 이로 인해 새 개체에 대한 오버헤드도 상대적으로 커집니다.

(2) Sun 객체 메모리 할당의 효율성을 위해 Hotspot JVM은 생성된 스레드에 대해 독립적인 공간인 TLAB(Thread Local Allocation Buffer)를 할당하며, 그 크기는 실행 상황에 따라 JVM에서 계산되므로 TLAB에 객체를 할당할 때 추가 공간이 필요하지 않습니다. Lock이므로 JVM은 스레드 객체에 메모리를 할당할 때 최선을 다해 TLAB에 메모리를 할당하려고 합니다. 이 경우 JVM에서 객체 메모리를 할당하는 성능은 기본적으로 C만큼 효율적이지만 객체가 너무 큰 경우 , 여전히 직접 힙 공간 할당 사용

(3) TLAB는 신세대 Eden Space에서만 작동하므로 Java 프로그램을 작성할 때 일반적으로 큰 개체보다 여러 개의 작은 개체를 할당하는 것이 더 효율적입니다.

(4) 새로 생성된 모든 개체는 차세대 용세대에 저장됩니다. Young Generation의 데이터가 하나 이상의 GC에서 살아남으면 Old Generation으로 전송됩니다. 에덴스페이스에는 항상 새로운 객체가 생성됩니다.

네 번째 블록: 메소드 영역

(1) Sun JDK에서 이 영역은 영구 세대라고도 알려진 PermanetGeneration에 해당합니다.

(2) 메소드 영역에는 로드된 클래스의 정보(이름, 수정자 등), 클래스의 정적 변수, 클래스의 최종 유형으로 정의된 상수, 클래스의 필드 정보, 클래스의 메소드 정보가 저장됩니다. , 개발자가 클래스 객체의 getName, isInterface 및 기타 메소드를 통해 프로그램의 정보를 얻을 때 이러한 데이터는 메소드 영역에서 오는 동시에 특정 조건에서는 전역적으로 공유됩니다. . 지역에 필요한 메모리가 허용된 크기를 초과하는 경우 OutOfMemory 오류 메시지가 발생합니다.

다섯 번째 블록: 런타임 상수 풀(Runtime Constant Pool)

고정된 상수 정보, 메소드, 필드 참조 정보를 클래스에 저장하며, 해당 공간은 메소드 영역에서 할당됩니다.

여섯 번째 블록: 네이티브 메서드 스택

JVM은 네이티브 메서드 스택을 사용하여 네이티브 메서드 실행을 지원합니다. 이 영역은 각 네이티브 메서드 호출의 상태를 저장하는 데 사용됩니다.

8. JVM 가비지 컬렉션

GC(Garbage Collection): GC에서 더 이상 사용되지 않는 객체를 재활용하는 방법을 GC에서 소비해야 하기 때문에 컬렉터라고 합니다. 약간의 자원과 시간을 들여 Java는 객체의 라이프 사이클 특성을 분석한 후 신세대와 구세대에 따라 객체를 수집하여 GC로 인해 애플리케이션에 발생하는 일시 중지를 최대한 단축합니다

(1) 신세대 Old 세대의 객체 컬렉션을 Minor GC라고 합니다.

(2) Old 세대의 객체 컬렉션을 Full GC라고 합니다.

(3) 프로그램에서 System.gc()를 적극적으로 호출하여 강제하는 GC입니다. 풀GC다.

다양한 객체 참조 유형, GC는 다양한 방법을 사용하여 재활용합니다. JVM 객체 참조는 4가지 유형으로 나뉩니다.

(1) 강력한 참조: 기본적으로 객체는 강력한 참조를 사용합니다(이 객체의 인스턴스에는 다른 객체 참조가 없으며 GC에서만 재활용됩니다).

(2) 소프트 참조: 소프트 참조는 Java에서 제공됩니다. 캐싱 시나리오에 더 적합합니다(메모리가 충분하지 않을 때만 GC됩니다)

(3) 약한 참조: GC 중에 확실히 GC에 의해 재활용됩니다

(4) 가상 참조: 가상 참조로 인해 그냥 익숙해졌습니다. 개체가 GC

인지 확인하세요.

주요 내용은 http://baike.baidu.com/link?url=r1DppgYdvfVHc2I0uVBfCgYd0MiNXrSMKU-E3AL_O5yvrQ3fL1FNvpNgS9MUk9H-#4 및 http://wenku.baidu.com/link? url =UXf-aoHl8YCX535q4G2qC48OExWk9ttLaIPW4Qn-GvdeSrM0WSjuAbq_78MJUrHq46ZS-8OsHDCMKkwmJTmXkPrkBZmbNqOA49iDyxsLIkm

1. JVM이란 무엇인가요?

JVM은 Java Virtual Machine의 약어입니다. JVM은 컴퓨팅 장치의 사양으로, 실제 컴퓨터에서 다양한 컴퓨터 기능을 시뮬레이션하여 구현하는 가상의 컴퓨터입니다. JVM(Java Virtual Machine)에는 바이트코드 명령어 세트, 레지스터 세트, 스택, 가비지 수집 힙 및 저장 방법 필드가 포함되어 있습니다. JVM은 특정 운영 체제 플랫폼과 관련된 정보를 보호하므로 Java 프로그램은 Java 가상 머신에서 실행되는 대상 코드(바이트코드)만 생성하면 되며, 수정 없이 다양한 플랫폼에서 실행될 수 있습니다. JVM이 바이트코드를 실행할 때 실제로는 궁극적으로 바이트코드를 특정 플랫폼에서 실행하기 위한 기계 명령어로 해석합니다.

Java 언어의 매우 중요한 특징은 플랫폼으로부터의 독립성입니다. 이 기능을 달성하려면 Java 가상 머신을 사용하는 것이 핵심입니다. 일반적인 고급 언어를 다른 플랫폼에서 실행하려면 최소한 다른 대상 코드로 컴파일해야 합니다. Java 언어 가상 머신이 도입된 이후에는 다른 플랫폼에서 실행될 때 Java 언어를 다시 컴파일할 필요가 없습니다. 자바 언어는 자바 가상 머신을 사용하여 특정 플랫폼과 관련된 정보를 보호하므로 자바 언어 컴파일러는 자바 가상 머신에서 실행되는 대상 코드(바이트코드)만 생성하면 되며 수정 없이 여러 플랫폼에서 실행될 수 있습니다. . JVM(Java Virtual Machine)은 바이트코드를 실행할 때 바이트코드를 특정 플랫폼에서 실행하기 위한 기계 명령어로 해석합니다. 이것이 바로 Java가 "한 번 컴파일하면 어디서나 실행"할 수 있는 이유입니다.

2. JRE/JDK/JVM은 어떤 관계인가요?

JRE(JavaRuntimeEnvironment, Java 런타임 환경)는 Java 플랫폼입니다. 모든 Java 프로그램은 JRE에서 실행되어야 합니다. 일반 사용자는 개발된 자바 프로그램을 실행하고 JRE를 설치하기만 하면 됩니다.

JDK(Java Development Kit)는 프로그램 개발자가 Java 프로그램을 컴파일하고 디버깅하는 데 사용하는 개발 도구 키트입니다. JDK 도구도 Java 프로그램이므로 실행하려면 JRE가 필요합니다. JDK의 독립성과 무결성을 유지하기 위해 JDK 설치 프로세스 중에 JRE도 설치의 일부입니다. 따라서 JDK 설치 디렉터리 아래에는 JRE 파일을 저장하는 데 사용되는 jre라는 디렉터리가 있습니다.

JVM(JavaVirtualMachine, Java Virtual Machine)은 JRE의 일부입니다. 컴퓨터의 다양한 기능을 실제 컴퓨터에 시뮬레이션하여 구현한 가상의 컴퓨터입니다. JVM에는 프로세서, 스택, 레지스터 등과 같은 자체적인 완전한 하드웨어 아키텍처가 있으며 해당 명령어 시스템도 있습니다. Java 언어의 가장 중요한 기능은 크로스 플랫폼 작동입니다. JVM을 사용하는 목적은 운영 체제 독립성을 지원하고 크로스 플랫폼을 구현하는 것입니다.

3. JVM 원리

JVM은 Java 컴파일러와 OS 플랫폼 사이의 가상 프로세서인 Java의 핵심이자 기초입니다. Java 바이트코드 프로그램이 실행될 수 있는 소프트웨어 방법을 사용하여 구현된 기본 운영 체제 및 하드웨어 플랫폼을 기반으로 하는 추상 컴퓨터입니다.

Java 컴파일러는 JVM을 지향하고 JVM이 이해할 수 있는 코드 또는 바이트코드 파일을 생성하기만 하면 됩니다. Java 소스 파일은 바이트코드 프로그램으로 컴파일되고, 각 명령어는 JVM을 통해 다양한 플랫폼용 기계어 코드로 변환되어 특정 플랫폼에서 실행됩니다.

4 JVM이 프로그램을 실행하는 과정

1) .class 파일 로드 2) 메모리 관리 및 할당 3) 가비지 컬렉션 수행

JRE(Java 런타임 환경)로 구성된 Java 프로그램 실행 JVM 링은 Java 프로그램이 실행되는 환경이기도 하지만 동시에 운영 체제이자 애플리케이션이며 프로세스이기도 합니다. 따라서 자체 코드 및 데이터뿐만 아니라 자체 실행 수명 주기도 갖습니다. 공간. JVM은 전체 jdk의 맨 아래에 있으며 운영체제의 상호작용을 담당하며 운영체제 환경을 보호하고 완전한 자바 실행 환경을 제공하는 역할을 하므로 가상 컴퓨터이기도 하다. JVM 환경은 jdk에서 Java.exe를 통해 JVM에 로딩된다. 1) JVM 로딩 환경 생성 및 구성 2) JVM.dll 로딩 3) JVM.dll 초기화 JNIENV(JNI 호출 인터페이스) 인스턴스에 마운트합니다. 4) JNIEnv 인스턴스를 호출하여 클래스 클래스를 로드하고 처리합니다.

5. JVM 라이프사이클

1) JVM 인스턴스는 프로세스 수준에서 시작되는 독립적으로 실행되는 Java 프로그램에 해당합니다.
a). Java 프로그램이 시작되면 JVM 인스턴스가 생성됩니다. public static void
main(String[] args) 함수가 있는 모든 클래스를 JVM 인스턴스
b) 실행을 위한 시작점으로 사용할 수 있습니다. main()은 프로그램의 초기 스레드에 대한 시작점 역할을 하며 다른 스레드는 이 스레드에 의해 시작됩니다. JVM 내부에는 데몬 스레드와 비데몬 스레드라는 두 종류의 스레드가 있습니다. main()은 비데몬 스레드에 속합니다. 데몬 스레드는 일반적으로 JVM 자체에서 사용됩니다. 생성된 것은 데몬 스레드입니다.
c) 죽음. 프로그램의 데몬이 아닌 스레드가 모두 종료되면 JVM이 종료됩니다. 보안 관리자가 허용하는 경우 프로그램은 Runtime 클래스 또는 System.exit()를 사용하여 종료할 수도 있습니다.

2) JVM 실행 엔진 인스턴스는 해당합니다. 사용자가 프로그램을 실행하는 스레드는 스레드 수준입니다

6. JVM 아키텍처


    ClassLoader(.class 파일을 로드하는 데 사용)
  • Execu tion 엔진(바이트코드 실행 또는 로컬 메소드 실행)
  • 런타임 데이터 영역(메서드 영역, 힙, Java 스택, PC 레지스터, 로컬 메소드 스택)
7.JVM 런타임 데이터 영역

첫 번째 블록: PC 레지스터

PC 레지스터는 각 스레드가 다음에 실행할 JVM 명령을 저장하는 데 사용됩니다. 메소드가 기본인 경우 PC 레지스터에 정보가 저장되지 않습니다.

두 번째 블록: JVM 스택

JVM 스택은 스레드 전용입니다. 각 스레드가 생성될 때 JVM 스택은 현재 스레드에 로컬 기본 유형 변수(Java에서 정의된 8개)를 저장합니다. 기본 유형: boolean, char, byte, short, int, long, float, double), 부분 반환 결과 및 기본이 아닌 유형의 객체는 JVM 스택의 힙을 가리키는 주소만 저장합니다.

세 번째 블록: Heap

JVM에서 객체 인스턴스와 배열 값을 저장하는 데 사용하는 영역입니다. Java에서 new를 통해 생성된 모든 객체의 메모리가 여기에 할당된다고 볼 수 있습니다. 힙은 GC가 회수될 때까지 메모리가 기다려야 합니다.

(1) 힙은 JVM의 모든 스레드에서 공유되므로 여기에 개체 메모리를 할당하려면 잠금이 필요하며 이로 인해 새 개체에 대한 오버헤드도 상대적으로 커집니다.

(2) Sun 객체 메모리 할당의 효율성을 위해 Hotspot JVM은 생성된 스레드에 대해 독립적인 공간인 TLAB(Thread Local Allocation Buffer)를 할당하며, 그 크기는 실행 상황에 따라 JVM에서 계산되므로 TLAB에 객체를 할당할 때 추가 공간이 필요하지 않습니다. Lock이므로 JVM은 스레드 객체에 메모리를 할당할 때 최선을 다해 TLAB에 메모리를 할당하려고 합니다. 이 경우 JVM에서 객체 메모리를 할당하는 성능은 기본적으로 C만큼 효율적이지만 객체가 너무 큰 경우 , 여전히 직접 힙 공간 할당 사용

(3) TLAB는 신세대 Eden Space에서만 작동하므로 Java 프로그램을 작성할 때 일반적으로 큰 개체보다 여러 개의 작은 개체를 할당하는 것이 더 효율적입니다.

(4) 새로 생성된 모든 개체는 차세대 용세대에 저장됩니다. Young Generation의 데이터가 하나 이상의 GC에서 살아남으면 Old Generation으로 전송됩니다. 에덴스페이스에는 항상 새로운 객체가 생성됩니다.

네 번째 블록: 메소드 영역

(1) Sun JDK에서 이 영역은 영구 세대라고도 알려진 PermanetGeneration에 해당합니다.

(2) 메소드 영역에는 로드된 클래스의 정보(이름, 수정자 등), 클래스의 정적 변수, 클래스의 최종 유형으로 정의된 상수, 클래스의 필드 정보, 클래스의 메소드 정보가 저장됩니다. , 개발자가 클래스 객체의 getName, isInterface 및 기타 메소드를 통해 프로그램의 정보를 얻을 때 이러한 데이터는 메소드 영역에서 오는 동시에 특정 조건에서는 전역적으로 공유됩니다. . 지역에 필요한 메모리가 허용된 크기를 초과하는 경우 OutOfMemory 오류 메시지가 발생합니다.

다섯 번째 블록: 런타임 상수 풀(Runtime Constant Pool)

고정된 상수 정보, 메소드, 필드 참조 정보를 클래스에 저장하며, 해당 공간은 메소드 영역에서 할당됩니다.

여섯 번째 블록: 네이티브 메서드 스택

JVM은 네이티브 메서드 스택을 사용하여 네이티브 메서드 실행을 지원합니다. 이 영역은 각 네이티브 메서드 호출의 상태를 저장하는 데 사용됩니다.

8. JVM 가비지 컬렉션

GC(Garbage Collection): 메모리에서 더 이상 사용되지 않는 객체를 재활용하는 방법을 GC에서 소비해야 하기 때문에 컬렉터라고 합니다. 리소스와 시간, 객체의 라이프 사이클 특성을 분석한 후 Java는 신세대와 구세대에 따라 객체를 수집하여 GC로 인해 애플리케이션에 발생하는 일시 중지를 최대한 단축합니다

(1) 신세대를 위한 Old 세대의 객체 컬렉션을 Minor GC라고 합니다.

(2) Old 세대 객체의 컬렉션을 Full GC라고 합니다.

(3) 프로그램에서 System.gc()를 적극적으로 호출하여 강제되는 GC는 Full입니다. GC.

다양한 객체 참조 유형, GC는 다양한 방법을 사용하여 재활용합니다. JVM 객체 참조는 네 가지 유형으로 나뉩니다.

(1) 강력한 참조: 기본적으로 객체는 강력한 참조를 사용합니다(이 객체의 인스턴스에는 다른 객체 참조가 없으며 GC 중에 재활용됨)

(2) 소프트 참조: 소프트 참조는 Java로 제공되는 애플리케이션으로 캐싱 시나리오에 더 적합합니다(메모리가 충분하지 않은 경우에만 GC됩니다) )

(3) 약한 참조 : GC 중에 GC에 의해 확실히 재활용됩니다

(4) 가상 참조: 가상 참조는 객체가 GC되었는지 여부를 아는 데만 사용되므로

위 내용은 JVM 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.