JVM:
1.什么是JVM
(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。
(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。
(3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
2.jdk,jre,jvm是什么关系
(1)JRE(Java Runtime Environment),也就是java平台。所有的java程序都要在JRE环境下才能运行。
(2)JDK(Java Development Kit),是开发者用来编译、调试程序用的开发包。JDK也是JAVA程序需要在JRE上运行。
(3)JVM(Java Virtual Machine),是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。
Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。
3.JVM原理
(1)jvm是java的核心和基础,在java编译器和os平台之间的虚拟处理器,可在上面执行字节码程序。
(2)java编译器只要面向jvm,生成jvm能理解的字节码文件。java源文件经编译成字节码程序,通过jvm将每条指令翻译成不同的机器码
,通过特定平台运行。
4.JVM执行程序的过程
1.加载.class文件
2.管理并分配内存
3.执行垃圾收集
JRE(java运行时环境)由JVM构造的java程序的运行环,也是Java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,
因此他也有他自己的运行的生命周期,也有自己的代码和数据空间。
JVM在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,
提供一个完整的Java运行环境,因此也就虚拟计算机。
操作系统装入JVM是通过jdk中Java.exe来完成,
通过下面4步来完成JVM环境:
(1).创建JVM装载环境和配置
(2).装载JVM.dll
(3).初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例
(4).调用JNIEnv实例装载并处理class类。
5.JVM生命周期
JVM实例对应了一个独立运行的java程序它是进程级别
(1) 启动。启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void
main(String[] args)函数的class都可以作为JVM实例运行的起点
(2) 运行。main()作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程,main()属于非守护线程,守护线程通常由JVM自己使用,java程序也可以表明自己创建的线程是守护线程
(3) 消亡。当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出
JVM执行引擎实例则对应了属于用户运行程序的线程它是线程级别的
JVM的位置:运行在操作系统(Window,Linux,Mac)上,jvm由C写的
栈,本地方法栈,程序记数器肯定不会有垃圾
栈和本地方法栈,程序以运行完毕,方法就会弹出去
所谓的JVM调优,一般都是调优堆和方法区
6.类加载器
作用:加载Class文件
public static void main(String[] args) {
//类是模板,对象是具体的
Class<car> carClass = car.class;
}
public class car {
public static void main(String[] args) {
//类是模板,对象是具体的
car car1 = new car();
car car2 = new car();
car car3 = new car();
System.out.println(car1.hashCode());//697960108
System.out.println(car2.hashCode());//943010986
System.out.println(car3.hashCode());//1807837413
Class<car> carClass = car.class;
Class<? extends car> aClass1 = car1.getClass();
Class<? extends car> aClass2 = car2.getClass();
Class<? extends car> aClass3 = car3.getClass();
System.out.println(aClass1.hashCode());//1627800613
System.out.println(aClass2.hashCode());//1627800613
System.out.println(aClass3.hashCode());//1627800613
}
}
一个模板new出来三个对象不同的hashCode值 就算new一万个对象也是相同的模板
比如说我们都是人,但每个人的身份证号不同一样
1.虚拟机自带的加载器
2.启动类(根)加载器
3.扩展类加载器
4.应用程序加载器
程序运行时会一层层往上找
查看类加载器代码 .getClassLoader();
public class car {
public static void main(String[] args) {
//类是模板,对象是具体的
car car1 = new car();
car car2 = new car();
car car3 = new car();
System.out.println(car1.hashCode());
System.out.println(car2.hashCode());
System.out.println(car3.hashCode());
Class<car> carClass = car.class;
Class<? extends car> aClass1 = car1.getClass();
ClassLoader classLoader = aClass1.getClassLoader();
//查看类加载器
System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@14dad5dc
System.out.println(classLoader.getParent());//sun.misc.Launcher$ExtClassLoader@7b3300e5
System.out.println(classLoader.getParent().getParent());//NULL
}
}
AppClassLoader//应用程序加载器
ExtClassLoader//扩展类加载器
NULL//1.不存在2.java程序获取不到双亲委派机制
代码实例:
package java.lang;
public class String {
//双亲委派机制:安全
//1.APP==》EXC==》BOOT(最终执行)
@Override
public String toString(){
return "hello";
}
public static void main(String[] args) {
String s = new String();
s.toString;
}
}
会报错:错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application
/*
1.类加载器收到类加载的请求
2.将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
3.启动类加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子加载器进行加载
4.重复步骤3
class Not Found~
null:java调用不到~ c,c++ 写的
java=C++ 去掉繁琐的东西,指针,内存管理 ==c++--
*/
白话文即,在类加载时,会一直向上委托,到根加载器(bootstrap),如果可以加载即加载,如果不可以,
则抛出异常通知其子加载器加载,其子加载器递归执行。最后都加载不上,抛出Class Not Found
Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。
ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。
AppClassLoader:主要负责加载应用程序的主函数类
只学习一点点部分 其他慢慢一起学习