`

【总结】java命令解析以及编译器,虚拟机如何定位类

阅读更多

      学Java有些日子了,一直都使用IDE来写程序。这样的好处就是能让我连如何用命令行编译,解释执行Java源代码都不知道,就更不清楚JDK中的编译器和虚拟机(包含字节码解释器)是如何定位到类文件的。悲哀呀.......


1、安装JDK,配置环境变量。

    不将JDK所在的目录配置到系统环境变量中,系统怎么能找到JDK中的编译器,解释器在哪呀?如果不指明JDK的bin文件夹的位置,在shell中是无法找到javac/java命令的。这点就不多说了。


2、编译,解释执行Java程序。【 javac命令/java命令】

    (1) Test.java源代码

//缺省包,该程序源代所在位置: e:/project/ Test.java

public class Test{
      .....
      public static void main(String[] args){
      .....
      }
} 



        编译命令: javac e:/project/Test.java    在e:/project目录下生成了Test.class

       注意: 如果想要将Test.class生成在指定目录下,可以使用javac -d命令,如 javac -d c:/ e:/project/Test.java   在c:/目录下生成T est.class(即e:/Test.class)

               javac -cp 中的-cp并不是指定Test.java的目录,这一点不要误解了。-cp/-classpath只能是指定类文件(.class文件)的路径。上面的命令不能写成:  java -cp e:/project Test.java


      解释执行命令 : 【 j ava -cp e:/project Test   将调用解释器执行e:/project中的Test.class字节码。

      注意: -cp 是指定用户类文件的位置,比如上面的Test.class的位置。这里因为要寻找Test.class类文件,而不是Test.java源代码文件,所以要通过-cp指定。千万没有这样的执行命令: java e:/project/Test


      (2) Test.java源代码

//缺省包,但源代码中引用了一个JAR包内的自定义类,这个JAR包位于c:/目录下

import net.single.util.SL;  //导入自定义JAR包中的类
public class Test{
       private SL aObject=new SL(); //初始化JAR中的SL类
       public static void main(String[] args){
       ......
       }
}



       编译命令: javac -cp c:/single.jar e:/project/Test.java 在e:/project目录下生成了Test.class

        注意: 如果当前你要编译的java文件中引用了其它的类,但该引用类的.class文件不在当前目录下(或在其他目录下,或在.zip/.jar内),这种情况下就需要在javac命令后面,加上-cp/-classpath参数来指明这些类的位置。 一般来说有三种指定方式:

              ① 绝对或相对路径:javac -cp c:/single.jar Test .java 或 javac -cp ../single.jar Test .java   (其中 .. 表示上一级目录
             
系统变量:javac -cp %CLASSPATH% Test .java (其中:%CLASSPATH%表示使用系统变量CLASSPATH的值进行查找,这里假设single.jar的路径就包含在CLASSPATH系统变量中)

              ③ 当前目录: javac -cp ./single.jar Test.java (其中 . 表示当前目录


       解释执行命令 :【 java -cp c:/single.jar;e:/project Test

       注意: ① -cp的路径不仅指定了所需要的single.jar的位置,还必须指出编译后的Test.class的位置。

              ② 类路径中的不同项目要用分隔符区分,Unix系统的分隔符是冒号(:),Windows的是分号(;)

            

      (3) Test.java 源代码

//该类在net.single包中,类中没有引入其他目录下的自定义类
package net.single;

public class Test{
      .....
      public static void main(String[] args){
       .....
      }
} 



          编译命令:【javac -d . e:/project/Test.java

        注意: ① 如果没有-d而直接编译javac e:/project/Test.java。将会在 e:/project 目录下直接生成一个Test.class,但此Test.class无法解释执行,因为它实际上在edu.single包中。所以必须将包一起编译出来,这里用了-d参数。

                ② 上面的编译结果将在e:/目录下 自动根据包的结构形式创建文件目录,e:/net/single/Test.class

        解释执行命令 : 【java -cp e:/ net.single.Test

           

     现在我们总结一下:

     [a.] 没有IDE环境,编译一个大型项目是很困难的,因为必须把需要被其他类引用的类先编译,而且最好把包结构一起编译出来。所以一般命令格式如下:

     编译: javac -cp (需要引入的类文件路径1;需要引入的类文件路径2;....) -d (编译出的类文件存放的位置目录) (待编译文件路径)

     执行: java -cp (需要解释执行的类文件路径) (带包的类文件)


      例:现在要编译一个类源码: Test.java,其中该类位于E:/project/下

            (1.  Test源代码中使用了一个JAR包中的类,这个single.jar包位于C:/目录下。

            (2.  Test源代码中使用了一个自定义类Content,这个类的源代码Content.java位于E:/下

            (3.  Test所在包为net.single,Content所在包为net.single.cont


      解决: 步1:由于Test使用了Content类,所以必须先编译Content,而且Content类在E:/目录下,而且 属于包net.single.cont

                        编译命令:  javac -d . e:/Content.java

                        编译结果:  在Content.java的当前目录下生成了一个  net/single/cont/Content.class   文件(带包结构),即e:/net/single/cont/Content.class

               步2:编译Test类,并指明所引入的single.jar包和Content.class的位置

                        编译命令:  javac -cp c:/single.jar;e:/net/single/cont -d . e:/project/Test.java

                        编译结果: 在Test的上一级目录下生成了一个 net/single/Test.class 文件,即e:/ net/single/Test.class

               步3:解释执行Test.class

                        执行命令:  java -cp c:/single.jar;e:/ net.single.Test

 

3、编译器,虚拟机如何定位到类的

package net.single;

import java.util.*;
import net.single.util.*;

public class Test{
     //SingleUtil类在c:/single.jar中的net.single.util包下
     private SingleUtil sut=new SingleUtil(); 
}

            编译命令:  javac -cp c:/single.jar -d . e:/project/Test.java

 

         编译器首先找到e:/project/Test.java。然后对Test源代码进行编译,当编译到创建SingleUtil类对象的语句时,编译器要开始寻找SingleUtil.class的位置。编译器首先查找包含这个类的所有包的位置,并查询所有的import指令,确定其中是否包含了被引用了的类。

       如上面的Test.java,编译器将试图查找java.lang.SingleUtil,java.util.SingleUtil,net.single.util.SingleUtil以及当前包中的SingleUtil(即net.single.SingleUtil)。编译器将在三个部分中查找类文件:

       (1) 在JDK的lib目录下的标准类库文件中查找java.lang,java.util和net.single.util包。显然只能找到java.lang和java.util包。然后在这两个包中查找SingleUtil类文件。当然是找不到的。

       (2) 在编译命令中-cp参数表明的类路径(C:/single.jar)下查找java.lang,java.util和net.single.util包。显然只能找到net.single.util包,然后在里面找到SingleUtil类文件。

      (3) 在Test.java的当前目录下查找SingleUtil,也是没有的。

       如果没有找到SingleUtil,或者找到多个SingleUtil。编译器报错。

 

 

     

 

11
0
分享到:
评论
1 楼 lfsfxy9 2011-08-24  
博主,你知道eclipse中如何对引入的jar包进行管理吗 ?

我想知道,项目中引入的jar包,被改名之后, import 引入关系依然成立.

这就是说,IDE认识的不是包名,而是具体的com.*.* .

你知道这里边的机制吗?

我想了解一下,谢谢.

相关推荐

    java虚拟机

    Java虚拟机(JVM,Java Virtual Machine)是Java平台的核心组成部分,它负责执行Java程序,为Java代码提供了跨平台的运行环境。Java虚拟机的概念始于Sun Microsystems,现在由Oracle公司继续发展和维护。JVM的设计...

    基于java实现的C语言编译器.zip

    总结,基于Java实现的C语言编译器项目是一个富有挑战性的任务,它涉及到编译原理的深度应用和Java技术的巧妙结合。通过这个项目,开发者不仅可以深化对编译器设计的理解,还能提升在Java语言和跨平台开发方面的技能...

    Java 虚拟机面试题全面解析(干货)

    JDK(Java Development Kit)是Java程序设计的核心,它包括Java编程语言、Java虚拟机(JVM)以及Java标准库。而JRE(Java Runtime Environment)是JDK的一个子集,它提供了Java程序运行时所需要的环境,包括Java...

    基于java实现的C语言编译器【100012136】

    在本项目中,"基于Java实现的C语言编译器【100012136】"是一个课程设计任务,目标是构建一个能够解析并处理C语言源代码的编译器。这个编译器的实现采用了Java编程语言,这使得它具有跨平台的能力,能够在多种操作...

    java实现tiger语言编译器

    Java实现Tiger语言编译器是一项涉及计算机科学与软件工程领域的复杂任务,主要涉及到编译原理、Java编程语言以及一种名为Tiger的语言。Tiger是一种教学目的的中级编程语言,设计用于展示现代编译器技术的关键概念。...

    java小型basic编译器

    1. **Java虚拟机(JVM)**:Java小型Basic编译器是用Java语言写的,因此它可以在任何安装了Java运行环境(JRE)的计算机上运行,因为Java程序依赖JVM来执行。JVM使得Java具有跨平台性,即“一次编写,到处运行”。 ...

    Java版pl0编译器

    **Java版PL0编译器**是一个实现编程语言解析与转换的工具,主要用来学习和理解编译原理。PL0是一种简单的、静态类型的、过程式的编程语言,它被设计成教学目的,便于理解和分析编译过程。在这个项目中,我们使用Java...

    现代编译器的Java实现(第二版).pdf 下载

    对于Java而言,编译器将Java源代码转换成字节码,这种字节码可以在任何安装了Java虚拟机(JVM)的平台上运行,体现了Java“一次编写,到处运行”的特性。 ### Java与编译器的关系 Java语言的编译器具有特殊性,...

    java类文件反编译器

    Java类文件反编译器是一种工具,主要用于将Java字节码(.class文件)转换回源代码(.java文件)。这种工具对于开发者来说非常有用,因为它允许他们查看和理解已经编译的Java程序的内部工作原理,特别是当原始源代码...

    Java虚拟机规范 深入java虚拟机

    它详细阐述了Java虚拟机(JVM)的工作原理,包括内存管理、类加载机制、字节码执行以及垃圾回收等核心概念。深入理解这些知识点对于提升程序性能、解决运行时问题以及设计高效的应用程序至关重要。 1. **JVM架构** ...

    JAVA虚拟机解读入门

    通过学习《JAVA虚拟机解读入门》,你将能够了解JVM如何加载和解析类,以及类加载的双亲委托模型。你还将掌握栈帧的工作方式,理解方法调用和返回的过程。此外,书中还会详细介绍垃圾收集的工作原理,包括如何判断...

    实战java虚拟机

    Java虚拟机是Java语言的核心组成部分,它负责解析和执行Java代码,实现跨平台的“一次编写,到处运行”。通过深入学习JVM,我们可以优化程序性能、解决内存泄漏问题,以及更好地理解和调试Java应用。 首先,我们要...

    解析Java虚拟机中类的初始化及加载器的父委托机制共14页

    本文将深入探讨Java虚拟机中的类初始化以及加载器的父委托机制。 一、类的加载 类加载是JVM启动时或运行中根据需要动态加载类到内存中的过程。这个过程分为三个阶段:加载、链接和初始化。 1. 加载:JVM通过类...

    Java语言规范和JVM虚拟机规范.zip

    本压缩包包含的文件详细阐述了Java编程语言的各个方面以及Java虚拟机(JVM)的工作原理。 **Java语言规范** Java语言规范定义了Java程序的语法、语义和程序行为。它涵盖了以下几个关键部分: 1. **基本概念**:...

    JAVA 反编译器

    3. **反编译过程**:反编译器首先解析.class文件中的字节码,然后根据JVM规范重建出类的结构,包括类名、方法、变量等。接着,它尝试恢复源代码的语句和表达式结构,这个过程可能不完美,因为字节码可能丢失了某些源...

    java虚拟机各种版本

    Java虚拟机的运行过程包括加载、验证、准备、解析、初始化等阶段,其中最重要的是解释器和JIT(Just-In-Time)编译器。解释器将字节码逐行解释执行,而JIT编译器会在运行时将热点代码编译成机器码,以提高运行效率。...

    java编译器

    3. **编译成字节码**:通过解析源代码,编译器生成中间表示(IR),然后将其转化为Java虚拟机(JVM)可理解的字节码。字节码是一种低级但平台无关的指令集,存储在.class文件中。 4. **优化**:为了提高程序的运行...

    java虚拟机学习

    Java虚拟机(JVM)是Java编程语言的核心组成部分,它为Java程序提供了运行环境。学习Java虚拟机对于深入理解Java程序的执行机制至关重要。这里我们将深入探讨Java虚拟机的几个关键知识点。 1. 类加载机制:Java程序...

    java类 反编译器

    下面我们将详细讨论Java类反编译器的工作原理、常用工具以及相关的知识点。 1. **Java字节码与反编译** Java程序在编译后会生成字节码,这是一种中间语言,由JVM(Java虚拟机)负责解释执行。字节码并不直接对应于...

    自己动手写Java虚拟机(GO语言)

    这本书的编写基于《深入理解Java虚拟机》第二版以及相关的Java规范,旨在帮助读者深入理解JVM的工作原理,并通过实践来提升技能。 首先,我们要了解Java虚拟机(JVM)的角色。JVM是Java平台的核心组件,它负责执行...

Global site tag (gtag.js) - Google Analytics