JVM이 무엇인지 첫째,
JVM (자바 가상 머신)을 실행할 수있는 자바 바이트 코드 파일 (예 개의 .class 파일) 가상 머신 프로세스입니다. 자바 소스 파일이 성공적으로 .class 파일로 컴파일 할 수있는 경우 JVM이 파일을 다른 플랫폼에 대해 동일한 기계 코드라고 설명을 .class 수 있기 때문에, JVM은 서로 다른 플랫폼에서 서로 다른 버전을 실행할 수 있습니다. JVM을의 존재, 자바는 플랫폼 독립적 인 언어로 알려져 있기 때문이다.
일반적으로 된 .java 파일이의 .class 파일 후 컴파일됩니다, 당신은 클래스 로더를 통과해야하기 전에 파일을 메모리로로드, 간단하게 그림을 살펴했다 :
둘째, 클래스 로딩 과정
클래스 로딩 과정은 : 부하 -> 연결 (확인 -> 제조 -> 분석) -> 초기화. 여기에 몇 가지 과정을들을 수 있습니다.
1로드
이것은 주로 클래스의 완전한 이름 통해 예컨대 java.lang.String의 벨트 패키지로 이러한 클래스 이름 취득한 바이트 코드 파일 후 정적 저장 구조 (간단한 것으로 이해 될 수있는 바이트 코드 파일이 나타내는 템플릿 개체 생성)이 메소드 영역이고, 힙의 액세스 방법 입력 영역 "템플릿"으로,이 클래스 타입 클래스 담당자의 객체를 생성하고,이 템플릿에 따라 생성 될 때 이후의 객체를 생성한다.
예를 들어, 때로는 반사에 의해 생성 된 객체는, 같은 객체를 생성하는 JDBC. 때 배우지 않았다 위해서, newInstance ()를 Class.getName ()에 ( "com.mysql.jdbc.Driver.class")를 통과 할 것이다 각각의 클래스 정규화 된 클래스 이름을 통해 다음 '템플릿'의 면적을 구하고에있어서, 상기 객체를 생성한다.
2, 검증
주요 검증 프로세스는로드 된 클래스의 정확성을 보장합니다. 우선은,의 .class 접미사 프로그램을 실행할 수있는 그 무엇에 해당 접미어 변화를 식별하는 경우, 파일 형식 사양 여부를 확인해야합니다, 그것은 문제가 매우 쉬울 것이다. 아마 같을 것이다 바이트 코드 파일을 살펴 보자 :
접두사 카페 아기 주 (커피 아기?)이, 바이트 코드 파일의 유효성 검사가 메이저와 마이너 버전 번호 및 기타 인증 정보가 포함됩니다 검증 포인트의 하나입니다.
3, 준비
这个阶段主要是给类变量(静态变量)分配方法区的内存并初始化。实例变量不是在这个阶段分配内存,实例变量是随着对象一起分配在堆中。另外,给静态变量初始化为零值或空值,比如public static int n=5;这里并不是马上给 n 这个变量赋值为 5,而是先将其赋值为 0,类似的,如果是引用数据类型,则默认为 null。还有一点需要注意的是,对于 final 类型的数据,必须在程序内给它赋值,系统不会自动初始化,例如 static String str = "hello" + “world”;String 是 final 类型的,在编译阶段就给它优化成 static String str = "helloworld” ,并且将 "helloworld" 放进了常量池。
4、初始化
这个阶段就是将静态变量赋值为初始值,还是 public static int n=5; 这回给 n 赋值为 5 了。
三、类加载器
启动类加载器是由C/C++写的,主要负责加载 jre\lib 目录下的类;扩展类加载器主要负责加载 jre\lib\ext 目录下的类;而应用程序类加载器主要负责加载我们自己编写的类;当然还能自己写类加载器,即自定义加载器。程序主要由前面三个类加载器相互配合加载的。
public class Main { public static void main(String[] args) { Main main = new Main(); System.out.println(main.getClass().getClassLoader()); System.out.println(main.getClass().getClassLoader().getParent()); System.out.println(main.getClass().getClassLoader().getParent().getParent()); } }
由于启动类加载器是 C/C++ 语言写的,所以输出为 null
双亲委派机制
在类加载的过程中,存在着双亲委派机制,即当要加载一个类时,先由父类加载器加载,当父类加载器没办法加载时,才由下面的加载器加载,来看一个程序:
package java.lang; // 自定义的包 public class String { public static void main(String[] args) { System.out.println("这是自定义的java.lang.String类"); } }
由于 jre\lib\ext 中存在 java.lang.String 类,当加载该类的时候,根据全限定名进行查找,找到后由启动类加载器加载,发现 String 类中不包含 main() 方法,因此程序出错。