java的JVM机制
1.jre:java运行环境 提供一个JVM和一些基础类库。
2.只安装jre以后,机器就具备了运行java程序的条件。但是不具备开发java程序的条件。安装JDK以后,在c:/program files/java/下有一个jre,在c:/program files/java/jdk/jre下还有一套jre,也就是说安装完jdk后系统出现了两套jre,这是为什么呢?
答案:JDK中的很多工具(如javac java)都是使用java本身开发的,这些工具都位于jdk安装目录\tools.jar中,因此要有一个JRE环境支持这些工具的运行,jdk目录下的那套jre就是为支持这些工具运行的。
既然系统中有两套jre,那么由谁来决定使用那一套呢?这个任务落在了java.exe身上。
当在命令行输入java.exe命令执行一个java程序时,它会安装下面方式来寻找合适的JRE:
1.首先查找自己的目录是否有JRE。
2.查看父目录是否有JRE。
3,查询系统配置(如在 windows系统中,查看注册表中的HKEY_LOCAL_MACHINE\software\java\Java Runtime Environment项目)
3.JVM Java Virtual Machine(java虚拟机) 它是一个虚拟出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。java虚拟机有自己完善的硬件架构,如处理器,堆栈,寄存器等,还具有相应的指令系统。
JVM屏蔽了与具体操作系统平台相关的信息,使得java程序只需要生成在java虚拟机上运行的目标代码,就可以再多种平台上不加修改地执行。
JVM的结构: JVM主要包含两个子系统和两个组件。两个子系统分别是Class loader子系统和Execution engine(执行引擎)子系统;两个组件分别是Runtime data area(运行时数据区域)组件和Native interface(本地接口)组件。
1.Class loader子系统的作用:根据给定的全限定名类名(如:java.lang.Object)来装载class文件的内容到Runtime data area中的method area(方法区域).java程序员可以extends java.lang.ClassLoader类来写自己的Class loader(一般一些大的J2EE中间件都会提供自己的类加载器 如WebLogic tomcat).(相当于计算机中的I/O系统)
2.Execution engine子系统的作用:执行classes中的指令。任何JVM sepcification实现(JDK)的核心都是Execution engine,不同的JDK例如Sun的JDK和IBM的JDK好坏主要就取决于他们各自实现的Execution engine的好坏。(这部分相当于JVM的CPU)
3.Native Interface组件:与native libraries交互。是与其他语言交互的接口。当调用native方法的时候,就进入了一个全新的并且不再受虚拟机限制的世界,所以也容易出现JVM无法控制的native heap OutOfMemory.(这部分可以想象成JVM的外设接口)
4.Runtime Data Area组件:这就是我们常说的JVM的内存了。它主要分为五个部分:
a.HEAP堆内存:用来存放java实例对象。
b.Method Area方法区:被装载的java类信息也就是字节码信息存放于此。
c.Java Stack栈空间:用于存放每个运行的Java线程的局部变量,操作数,中间结果,以及执行上下文信息(JDK5.0之前大小为256K,之后为1M)。
d.Program Count程序计数器:每一个java线程都有它自己的PC寄存器,也是该线程启动时创建的。PC寄存器的内容总是指向下一条将被执行 指令的地址,这里的地址可以是一个本地指针,也可以使在方法区中相对于应用该方法起始指令的偏移值。
e.Native Method Stack本地方法栈:保存本地方法进入区域地址。
以上五部分只有Heap和Method Area是被所有线程共享使用的,而Java stack,Program counter和Native method stack是以线程为粒度的,每个线程独自拥有自己的部分。
【Java的类加载器】
Java语言室一种先天具备动态性的语言。之所以具备动态性正是由于Java类装载器的存在。
1.类加载器的两种装载方式: 预先载入和按需载入
通常基础类库需要预先载入(常驻内存 GC不会回收) 自定义类库需要按需载入(使用时载入,使用完毕有垃圾收集器负责释放)
小技巧:可以通过java -verbose:class查看命令在执行时,JVM都加载了哪些类。