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

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

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

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

(1) Test.java源代码

<span style="font-size: small;">//缺省包,该程序源代所在位置: e:/project/ Test.java

public class Test{
      .....
      public static void main(String[] args){
      .....
      }
} </span>

编译命令: 【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源代码

<span style="font-size: small;">//缺省包,但源代码中引用了一个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){
       ......
       }
}</span>

编译命令: 【 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 源代码 

<span style="font-size: small;">//该类在net.single包中,类中没有引入其他目录下的自定义类
package net.single;

public class Test{
      .....
      public static void main(String[] args){
       .....
      }
} </span>

编译命令:【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。编译器报错。

【总结】java命令解析以及编译器,虚拟机如何定位类的更多相关文章

  1. Java泛型解析(03):虚拟机运行泛型代码

    Java泛型解析(03):虚拟机运行泛型代码      Java虚拟机是不存在泛型类型对象的,全部的对象都属于普通类,甚至在泛型实现的早起版本号中,可以将使用泛型的程序编译为在1.0虚拟机上可以执行的 ...

  2. java-关于java_home配置,classpath配置和javac,java命令,javac编译器,和java虚拟机之间的关系

    在每个人学习java的第一步,都是安装jdk ,jre,配置java_home,classpath,path. 为什么要做这些?在阅读java-core的时候,看到了原理,p141. 一 关于类的共享 ...

  3. java命令行运行jar里的main类

    一般运行包含manifest的jar包,可以使用 java -jar <jar-file-name>.jar 如果jar里没有 manifest,则可以使用 java -cp foo.ja ...

  4. java复习要点(一)------- java语言的特点、java的工作原理、配置环境变量、java命令的使用

    一.java语言的特点: (1)简单并面向对象 (2)鲁棒并安全: java语言在编译及运行程序时,都要进行严格的检查,防止不匹配问题的发生.如果引用一个非法类型,或执行一个非法类型操作,java减肥 ...

  5. Java泛型解析(04):约束和局限性

    Java泛型解析(04):约束和局限性           前两节.认识和学习了泛型的限定以及通配符.刚開始学习的人可能须要一些时间去体会到泛型程序设计的优点和力量,特别是想成为库程序猿的同学就须要下 ...

  6. Java 命令行编译项目

    如果是用Exlipse, 第三方的包可以放在eclipse文件夹的jre包的lib文件夹中! (初学者的一些总结-高手们勿喷哈-) 原因: 以前一直用Eclispe编程环境运行Java.非常舒服,就像 ...

  7. Java泛型解析(01):认识泛型

    Java泛型解析(01):认识泛型 What      Java从1.0版本号到如今的8.中间Java5中发生了一个非常重要的变化,那就是泛型机制的引入.Java5引入了泛型,主要还是为了满足在199 ...

  8. Java泛型解析(02):通配符限定

    Java泛型解析(02):通配符限定      考虑一个这种场景.计算数组中的最大元素. [code01] public class ArrayUtil { public static <T&g ...

  9. 手写JAVA虚拟机(二)——实现java命令行

    查看手写JAVA虚拟机系列可以进我的博客园主页查看. 我们知道,我们编译.java并运行.class文件时,需要一些java命令,如最简单的helloworld程序. 这里的程序最好不要加包名,因为加 ...

随机推荐

  1. android数独游戏

    最近没事干,照着视频教程写了一个数独游戏,很粗糙还有很多要修改的地方.下面就来说说这个游戏吧 1.自定义一个View控件,用来在屏幕上显示一个9*9的格子,其实就是横着画8条线,竖着画8跳线,然后将其 ...

  2. C# 非独占延时函数 非Sleep

    在C#窗口程序中,如果在主线程里调用Sleep,在Sleep完成之前, 界面呈现出假死状态,不能响应任何操作! 下边实现的是非独占性延时函数,延时过时中界面仍可响应消息: public static ...

  3. 使用cronolog切割tomcat catalina.out文件

    今天查看之前配置的tomcat发现catalina.out文件已经增大到接近5G,过不了多久就会将所在分区撑爆. 搜集了一下,大部分都使用cronolog切割catalina.out文件.按照这个方式 ...

  4. 【Binary Tree Preorder Traversal】cpp

    题目: Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binar ...

  5. JS学习笔记-1--基本知识和注意事项

    1.JS开始的目的主要是验证表单的输入验证 2.是一种具有面向对象能力的.解释型语言.是基于事件驱动的相对较安全的客户端脚本语言 3.JS 特点:松散型:变量不具备一个明确的类型:   对象属性:把属 ...

  6. Mac上安装 mySql

    今天在mac系统上安装了 mySql 和大家分享下 安装的过程.. 首先 第一步 需要在oracle的网站下载 mysql 的mac 版本. 下载地址如下: http://www.mysql.com/ ...

  7. share干什么的

    share到底干什么的 //--------------------打开GameServer,share中加载------------------------- .加载nBodyID //玩家的nBo ...

  8. spring mvc注解@RequestParam

    在spring mvc 的使用过程中 获取 页面传来的参数的时候,我平时都习惯  @RequestParam String name,突然有一天我发现 直接在方法参数后面写 String name , ...

  9. Samy XSS Worm之源码讲解

    说到Web安全和XSS跨站脚本技术,几乎所有的书都会提到Samy Worm,这是在2005年感染了mySpace社交网络上百万用户的蠕虫.正如Morris蠕虫是互联网第一个蠕虫, Samy Worm则 ...

  10. YTKNetwork

    YTKNetwork 是猿题库 iOS 研发团队基于 AFNetworking 封装的 iOS 网络库,其实现了一套 High Level 的 API,提供了更高层次的网络访问抽象. YTKNetwo ...