java的运行环境解析
-
jdk 和 jre 的区别
Jdk:java Development Kit。Jdk中有一个jre。Jdk的bin目录下有java(运行) 和 javac(编译)。Jdk的lib下有一个tools.jar
为什么tools.jar在jdk中
Tool.jar 解压后就剩了
编译和运行需要的都是toos.jar里面的类 , 分别是
sun.tools.java.*;
sun.tools.javac.*;
Jre:java runtime Environment。Jre的bin目录下仅有java命令。说明,只要你是编译过后的class文件,即使只有jre,也可以运行。但是不可以编译。因为是运行时只要jre就可以。所以jvm在jre中。
另外因为是运行。所以rt.jar就在jre的lib目录下了
rt.jar、 toos.jar
rt.jar:java运行时所需要的的jar包
toos.jar:java编译和运行时都需要的jar包
Path 和 classpath 到底是什么
Path:环境变量,我们每次都会讲java、maven、mysql等的bin目录放到path下,就是因为可以在任何目录下识别bin目录下的命令
Classpath:可能有人会说src就是classpath,那就错了,classpath的作用是我们java程序运行时,会需要各种各样的class文件,这时候classloader(类加载器 )就需要从我们的classpath下去找,rt.jar 默认就在 根classloader的加载路径里面 放在claspath是多此一举
Classpath到底是什么呢。Class文件,当然是我们编译过后的
这个编译过后的classes文件夹,就是我们的classpath
类加载及三种类加载器
1.首先要复习一下什么是类加载
类加载:当JVM第一次使用到一个类时,根据classpath环境变量下的配置,找到类的class文件,将其加载到虚拟机(这只是其中一步)
classpath:是不是很熟悉,其实在jdk1.5之后就不用配置了,之前是怎么配置的呢?
%JAVA_HOME%/lib/tools.jar 放到classpath的环境变量中
tools.jar
当我们javac编译的时候,它为我们提供了编译的工具。
rt.jar(Runtime)
包含了最基本的包,java.lang包,util包,
2.完整类加载的过程
①加载:就是将类的class文件读入到内存中,并为之创建一个Java.lang.Class的对象,也就是说,当程序中第一次使用任何类型时,系统都会为之创建一个java.lang.Class对象
类的加载是由类加载器完成的,类加载器通常是由JVM提供的,JVM提供的这些类加载器通常被称为系统类加载器。
类加载器无需等到"首次使用"该类时才加载该类,Java虚拟机规范允许系统先加载某些类
②验证:主要是验证字节码文件是够符合规范,语义是否合法,是否符合逻辑,有没有被篡改字节码文件
③准备:准备为
静态的资源和属性分配
内存空间,并设置默认值④解析:将符号引用解析成直接引用,直接引用是指向目标的指针
⑤初始化:为类的静态成员赋值,当准备阶段的时候其实是赋予默认值
3.类加载的时机
①new
②访问静态的的属性或者方法
注意:当静态的属性被finally修饰,而且直接在声明时初始化,name这个变量相当于"宏变量",此时即使访问这个值,也不会导致该类被初始化
③new 子类(首先会初始化子类的父类)
④Class.forName();(反射)
4.类加载器
①根类加载器:它用来加载Java的核心类,是由C++实现的,用来加载rt.jar
bootstrapClassLoader
②扩展类加载器:
extensionClassLoader lib/ext/*.jar
③系统类加载器:
AppClassLoader 加载自定义类
5.类加载机制
①全盘负责:当一个类加载器负责加载某个类的class时,该class所依赖和引用其他Class也将有该类加载器全责载入
②双亲委派:先让父类加载器试图加载该Class,如果父类无法完成该类加载任务,则自己去加载(子加载器才会去加载)
③缓存机制:保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器首先会从缓存中搜索该Class,只有当缓存中不存在该Class对象是,系统才会去加载该类的字节码文件,生成该类的Class对象,存入缓存区中,这就是为什么修改了Class后,必须重启Jvm