`
weitao1026
  • 浏览: 1053215 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

jdk,jre,jvm ,jit的意思

 
阅读更多
有三个名词需要分清
jdk:是java开发用的,里面有编译器。
jre:是运行java程序用的,如果你只是需要运行程序,那只装jre就可以了
jvm:jrejdk都需要jvm的支持,jvm是运行和编译java程序的核心。

JDK包含虚拟机和开发环境,具体解释如下:
1.sdk和jdk和jre之间的区别:·SDK(Software Development Kit)一般指软件开发包,可以包括函数库、编译程序等。 
·JDK(Java Development Kit)是面向JAVA开发人员使用的SDK,它提供了Java的开发环境和运行环境。 
·JRE(Java Runtime Enviroment)是指Java的运行环境,是面向Java程序的使用者,而不是开发者。 
2.JRE
的地位就象一台PC机一样,写好的Win32应用程序需要操作系统运行,同样的,编写的Java程序也必须要JRE才能运行。所以装完
JDK后,如果分别在硬盘上的两个不同地方安装了两套JRE,那么电脑有两台虚拟的Java 
PC机,都具有运行Java程序的功能。

JDK JVM JRE Java虚拟机概念区别和一个类加载器实例

本来是要分析AOP源码的,它需要分析动态代理的源码,动态代理又需要分析类的加载和生成的过程,所以进入到了这篇的学习,现做一下总结:

1.一些概念

1)什么是JDK?

JDK就是Java Development Kit.简单的说JDK是面向开发人员使用的软件开发包,它提供了Java的开发化境和运行环

2)什么是JRE

Java Runtime Enviroment是指Java的运行环境,是面向Java程序的使用者,而不是开发者。

 

3)什么是JVM?

JVM -- java virtual machineJVM就是我们常说的java虚拟机,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行

4)什么Java虚拟机

JVM其实就是Java虚拟机

5)之间的关系?

JDK安装之后内部包含了JRE,这个JRE是供开发使用的;其实在安装JDK的过程中外部也会有一个JRE,这个是给普通使用者使用的,可以用来运行编译后的字节码,当我们进行开发时要指定JRE的安装目录,这个时候应该选择JDK下面的JRE。另外JRE中的bin目录就是Java虚拟机,我们需要运行Java程序时需要安装Java虚拟机,就是指安装Java的运行环境JRE(包含bin目录)的过程。

2.从一张图看它们的区别(来自http://blog.csdn.net/luanlouis/article/details/24589193),以及引申到类加载器实例


Java编译器指的就是JDK中的javac.exe,JRE中是没有的,不过一般来说IDE中如Eclipse都包含了这个。简单梳理下代码的执行流程,首先是源文件,然后经过Java编译器生成.class的二进制文件,这个文件经过本地或者网络(一般是本地,如果要处理远程的class文件,需要自定义类加载器),然后经过JDK中的类加载器的和Java类库和校验。然后再由Java解释器(java.exe)和即时编译器的处理。

Java解释器:是JRE的一部分,能够把.class的字节码一行一行直接翻译成机器码,然后由运行期系统执行。

即时编译(Just-in-time compilation:JTI):是JRE的一部分,又叫实时编译,是一种把字节码翻译成机器码并且缓存起来以降低性能耗损,被用来改善虚拟机性能。

然后处理之后的机器码就由运行期系统来指定,运行期系统执行机器码同时还通过诸如本地方法与操作系统进行交互。这个就是类从编译到运行的过程。

3.下面讲述类加载器

1) 自定义类加载器如何运行的?

先要明确自定义类的加载器会是如何运行的,才能够自定义类加载器,下面一个简单的分析:

我们找到类加载所在的类java.lang.ClassLoader(这个就是我们自定义类加载器要继承的类), 然后发现如下过程


进入loadClass:


进入findClass:


发现这个方法直接抛出异常,原来是要我们自定义时进行重写的。至于重写的时候应该写那些内容,执行哪些操作,上面叙述的是follow the delegation model for loading classes, and will be invoked by the {@link #loadClass <tt>loadClass</tt>} method after checking the parent class loader for the requested class,它的意思以后深究,总之是要完成这样的功能:即找到类,然后进行加载。

2)如何自定义类加载器?

自定义类加载器需要继承ClassLoader类,重写findClass方法,在findclass方法中完成A)找到类,放入字节数据

B)分析字节数据,加载类,如下:

MyClassLoader.java

 

[java] view plain copy
 
  1. package day_20160929;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.InputStream;  
  7.   
  8. public class MyClassLoader extends ClassLoader{  
  9.     private String name;//类加载器名字  
  10.     private String path;//加载类的路径  
  11.     private final String fileType = ".class";//class文件的扩展名  
  12.       
  13.     public MyClassLoader(String name){  
  14.         super();  //让系统类加载器成为该类加载器的父加载器  
  15.         this.name = name;  
  16.     }  
  17.       
  18.     public MyClassLoader(ClassLoader parent,String name) {  
  19.         super(parent);  
  20.         this.name = name;  
  21.     }  
  22.       
  23.     @Override  
  24.     public String toString() {  
  25.         return this.name;  
  26.     }  
  27.   
  28.     public String getPath() {  
  29.         return path;  
  30.     }  
  31.   
  32.     public void setPath(String path) {  
  33.         this.path = path;  
  34.     }  
  35.       
  36.      /** 
  37.      * @param 类文件的名字 
  38.      * @return 类文件中类的class对象 
  39.      *  
  40.      * 在这里我们并不需要去显示的调用这里的findclass方法,在上篇文章中,我们通过查看 
  41.      * loadclass的源码可以发现,她是在loadclass中被调用的,所以这里我们只需重写这个方法, 
  42.      * 让它根据我们的想法去查找类文件就ok,他会自动被调用 
  43.      *  
  44.      *  
  45.      * defineClass()将一个 byte 数组转换为 Class 类的实例。必须分析 Class,然后才能使用它 
  46.      * 参数: 
  47.          * name - 所需要的类的二进制名称,如果不知道此名称,则该参数为 null 
  48.          * b - 组成类数据的字节。off 与 off+len-1 之间的字节应该具有《Java Virtual Machine Specification            》定义的有效类文件的格式。 
  49.          * off - 类数据的 b 中的起始偏移量 
  50.          * len - 类数据的长度  
  51.      */  
  52.     @Override  
  53.     public Class<?> findClass(String name) throws ClassNotFoundException {  
  54.         byte[] data = this.loadClassData(name);//获得类文件的字节数组  
  55.         return this.defineClass(name, data, 0, data.length);//  
  56.     }  
  57.       
  58.     /** 
  59.      *  
  60.      * @param 类文件的名字 
  61.      * @return 类文件的 字节数组 
  62.      * 通过类文件的名字获得类文件的字节数组,其实主要就是用 
  63.      * 输入输出流实现。 
  64.      */  
  65.     private byte[] loadClassData(String name) {  
  66.         InputStream is = null;  
  67.         byte[] data = null;  
  68.         ByteArrayOutputStream baos = null;  
  69.         try {  
  70.             name = name.replace(".""\\");  
  71.             is = new FileInputStream(new File(path + name + fileType));  
  72.             baos = new ByteArrayOutputStream();  
  73.             int ch = 0;  
  74.             while (-1 != (ch = is.read())) {  
  75.                 baos.write(ch);  
  76.             }  
  77.             data = baos.toByteArray();  
  78.         } catch (Exception ex) {  
  79.             ex.printStackTrace();  
  80.         } finally {  
  81.         try {  
  82.             is.close();  
  83.             baos.close();  
  84.         } catch (Exception ex) {  
  85.             ex.printStackTrace();  
  86.         }  
  87.     }  
  88.     return data;  
  89. }  
  90.       
  91. }  

 

App.java

 

[java] view plain copy
 
  1. package day_20160929;  
  2.   
  3. /*测试的基础类App*/  
  4. public class App {  
  5.   
  6.     public void appSay(){  
  7.         System.out.println("App.appSay()");  
  8.     }  
  9.       
  10. }  
Main.java

 

 

[java] view plain copy
 
  1. package day_20160929;  
  2.   
  3. public class Main {  
  4.       
  5.     public static void main(String[] args) {  
  6.         /*创建loader1类加载器,设置父类加载器为系统类加载器*/  
  7.         MyClassLoader loader1 = new MyClassLoader("loader1");  
  8.         loader1.setPath("E:\\workspaces\\myapp\\target\\test-classes\\");  
  9.           
  10.         /*创建loader2类加载器,设置父类加载器为loader1*/  
  11.         MyClassLoader loader2 = new MyClassLoader(loader1,"loader2");  
  12.         loader2.setPath("E:\\workspaces\\myapp\\target\\test-classes\\");  
  13.           
  14.         /*创建loader3类加载器,设置父类加载器为根类加载器*/  
  15.         MyClassLoader loader3 = new MyClassLoader(null,"loader3");  
  16.         loader3.setPath("E:\\workspaces\\myapp\\target\\test-classes\\");  
  17.           
  18.          try {  
  19.             test(loader1);  
  20.             System.out.println("----------");  
  21.             test(loader2);  
  22.             System.out.println("----------");  
  23.             test(loader3);  
  24.         } catch (Exception e) {  
  25.             e.printStackTrace();  
  26.         }  
  27.     }  
  28.       
  29.     public static void test(ClassLoader loader) throws Exception {  
  30.         /*加载类*/  
  31.         Class clazz = loader.loadClass("day_20160929.App");  
  32.         System.out.println("Main.test():"+clazz.getCanonicalName());  
  33.         /*创建类实例*/  
  34.         Object object = clazz.newInstance();  
  35.         System.out.println("Main.test():"+object.toString());  
  36.     }  
  37.       
  38. }  

 



将上面的执行过程概括一下:

 

首先在构造方法中,我们可以通过构造方法给类加载器起一个名字,也可以显示的指定他的父类加器器,如果没有显示的指出父类加载器的话他默认的就是系统类加载器。由于我们继承了ClassLoader类,所以它自动继承了父类的loadclass方法。我们前面看了loadclass的源码知道,它调用了findclass方法去查找类文件。所以在这里我们重写了ClassLoader的findclass方法。在这个方法中首先调用loadClassData方法,通过类文件的名字获得类文件的字节数组,其实主要就是用输入输出流实现。然后调用defineClass()将一个 字节 数组转换为 Class 类的实例。

注:整个类加载会按照这个顺序来调用loadClass->findClass->defineClass,我们要做的就是在findClass方法中,获得类的字节数组,然后再调用系统的defineClass方法,其实整个过程我们做的就是分析类文件,得到它的字节数组,其他的由系统来做。

3)为什么要自定义类加载器?

自定义类加载器的其中一个应用场景是:通过网络来传输 Java 类的字节代码(.class文件),为了保证安全性,这些字节代码经过了加密处理。在接收的时候,就需要自己的类加载器来从某个网络地址上读取加密后的字节代码,接着进行解密和验证,最后定义出要在 Java 虚拟机中运行的类。

总结:主要学习了Java一些基本概念和类加载器的执行流程以及如何自定义类加载器~    后面会学习动态代理和AOP相关的内容。

上面遗漏了很多的问题,其实下面这些问题都是由这篇文章引出,然后主动学习总结的:

1)为什么自定义类加载器会执行findClass方法?

2)什么是双亲委派模型?其中的各个加载器分别加载哪些类?

3)这个模型与类的生命周期由什么样的对应关系?

4)刚才我们在使用自定义类加载器加载类时,为什么类要使用"day_20160929.App"这样的全限定类名,使用App不行么?

5)类的生命周期是怎样的?

 
分享到:
评论

相关推荐

    Java中JDKJRE和JVM解析.doc

    ### Java中的JDK、JRE与JVM解析 #### 一、引言 在Java编程领域,JDK、JRE和JVM这三个概念是至关重要的基础知识点。虽然它们经常被提及,但很多人仍然对它们之间的关系和各自的功能感到困惑。这篇文章将深入探讨这...

    Java中的数据类型及JDK, JRE, 和 JVM解释及关系.zip

    在Java的世界里,了解数据类型、JDK(Java Development Kit)、JRE(Java Runtime Environment)以及JVM(Java Virtual Machine)的关系至关重要,它们是Java程序运行的基础。 首先,让我们深入探讨Java中的数据...

    java1.8jdk/jre.rar

    Java 1.8 JDK/JRE 是Java开发工具包和Java运行环境的组合,对于任何Java开发者来说都是必不可少的基础。在本压缩包中,你将找到用于编写、编译和运行Java应用程序的所有必要组件。让我们深入了解一下这两个核心组件...

    openjdk8u60+jvm jdk源码+jvm源码

    JDK 是开发和运行 Java 应用程序所需的一组工具和库的集合,包括 JRE(Java Runtime Environment)和开发工具。 JVM(Java Virtual Machine)是 JDK 的核心组成部分,它负责执行字节码,提供了一个“一次编写,到处...

    jdk6u43 64位,jdk/jre完整版

    在JDK 6中,HotSpot虚拟机使用了Just-In-Time (JIT) 编译器,能够动态优化代码,提高运行效率。 3. **JRE**(Java Runtime Environment):包含了运行Java应用程序所需的基本组件,包括Java虚拟机(JVM)、类库以及...

    jdk1.8.0_281.zip

    JDK(Java Development Kit)是Oracle公司发布的用于开发Java应用程序的软件开发工具包,它包含了Java运行环境(JRE)、编译器、调试器以及其他工具,使得开发者能够编写、测试和部署Java应用。JDK 1.8.0_281是这个...

    jdk1.6.0_20

    8. 性能提升:通过优化JIT(Just-In-Time)编译器和内存管理,JDK 1.6在许多场景下都实现了性能提升。 三、文件结构 "jdk1.6.0_20"压缩包内通常包含以下主要文件和目录: - bin:存放可执行命令,如javac、java、...

    jdk-8u391-windows-x64

    JDK 8u391是Oracle公司发布的一个针对Windows x64平台的更新版本,它包含了Java运行时环境(Java Runtime Environment,JRE)和一系列开发工具,如Java编译器(javac)、Java调试器(jdb)、Java文档生成器(javadoc...

    Oracle JDK11 Windows 压缩版

    Oracle JDK11的JVM采用了JIT(Just-In-Time)编译器,能提高程序运行效率。 3. **Java运行时环境(JRE)**:JRE是运行Java应用程序所必需的环境,包括JVM、类库和其他必要的组件。 4. **Java应用启动器(java)**...

    java运行环境jre

    JVM通过Just-In-Time (JIT) 编译器将部分字节码转化为机器码,从而提高程序的运行效率。JVM的内存模型,包括堆、栈、方法区等,对于理解和优化Java程序的性能至关重要。 描述中提到的"jar包"是Java Archive的缩写,...

    jre1.8.0_131.rar

    Java Runtime Environment(JRE)是Java开发工具集(Java Development Kit,JDK)的一个组成部分,主要负责提供Java程序运行所需的环境。JRE1.8.0_131是Oracle公司发布的一个特定版本,它包含了Java虚拟机(JVM)、...

    jre6 java运行环境免安装版

    7. **性能优化**: JRE6中包含的JVM进行了多方面的性能优化,例如更高效的垃圾回收算法、更快的字节码解释器以及对Java代码的即时编译(JIT),这些都显著提升了Java程序的运行速度。 8. **API更新**: JRE6还引入了...

    jdk-21-windows-x64-bin.zip

    JDK 21的JRE可能会更新JVM的HotSpot或OpenJ9实现,提供更好的性能和内存管理,比如改进的JIT编译器、新的垃圾收集器策略等。 4. **开发工具**:JDK还包括一系列开发工具,如Javadoc(用于生成API文档)、JAR(打包...

    Java Runtime Environment JRE 1.4.2

    在性能方面,JRE 1.4.2引入了Just-In-Time (JIT) 编译器的优化,能够将频繁执行的热点代码转换为本地机器码,显著提高了执行速度。此外,它还加强了Java的内存模型,确保了多线程环境下的正确性和一致性。 最后,...

    JVM 77 道面试题及答案.docx

    8. JRE、JDK、JVM 及 JIT 之间的区别:JRE 代表 Java 运行时,JDK 代表 Java 开发工具,JVM 代表 Java 虚拟机,JIT 代表即时编译。 9. Java 堆空间及 GC:Java 堆空间是 JVM 内存的一部分,用于存储 Java 对象。GC ...

    jdk1.8.0_161.zip

    3. **Java运行时环境(JRE)**:虽然JRE不是直接包含在JDK中,但JDK安装会同时安装JRE,它包含了运行Java应用所需的基本组件,如JVM、核心类库等。 4. **开发工具**:如`jar`命令用于打包和管理Java档案文件,`...

    Jre 8 64位

    2. **模块系统(Project Jigsaw)**:虽然这个特性是在JDK 9中正式引入的,但JRE 8的发布预示着模块化系统的初步规划。模块化有助于提高代码的组织性和可维护性,同时也减少了程序的启动时间和内存占用。 3. **...

    jdk17中文说明文档

    4. **JVM(Java虚拟机):** 包括内存模型、垃圾收集、类加载机制、JIT编译器优化等内容。 5. **模块系统(Project Jigsaw):** JDK 9引入的模块系统,增强了代码的组织和封装。 6. **Java编程最佳实践:** 如...

Global site tag (gtag.js) - Google Analytics