javac命令

javac命令初窥

注:以下红色标记的参数在下文中有所讲解。

用法: javac <options> <source files>
其中, 可能的选项包括:
  -g                         生成所有调试信息
  -g:none                    不生成任何调试信息
  -g:{lines,vars,source}     只生成某些调试信息
  -nowarn                    不生成任何警告
  -verbose                   输出有关编译器正在执行的操作的消息
  -deprecation               输出使用已过时的 API 的源位置
  -classpath <路径>            指定查找用户类文件和注释处理程序的位置
  -cp <路径>                   指定查找用户类文件和注释处理程序的位置
  -sourcepath <路径>           指定查找输入源文件的位置
  -bootclasspath <路径>        覆盖引导类文件的位置
  -extdirs <目录>              覆盖所安装扩展的位置
  -endorseddirs <目录>         覆盖签名的标准路径的位置
  -proc:{none,only}          控制是否执行注释处理和/或编译。
  -processor <class1>[,<class2>,<class3>...] 要运行的注释处理程序的名称; 绕过默认的搜索进程
  -processorpath <路径>        指定查找注释处理程序的位置
  -d <目录>                    指定放置生成的类文件的位置
  -s <目录>                    指定放置生成的源文件的位置
  -implicit:{none,class}     指定是否为隐式引用文件生成类文件
  -encoding <编码>             指定源文件使用的字符编码
  -source <发行版>              提供与指定发行版的源兼容性
  -target <发行版>              生成特定 VM 版本的类文件
  -version                   版本信息
  -help                      输出标准选项的提要
  -A关键字[=值]                  传递给注释处理程序的选项
  -X                         输出非标准选项的提要
  -J<标记>                     直接将 <标记> 传递给运行时系统
  -Werror                    出现警告时终止编译
  @<文件名>                     从文件读取选项和文件名

-g、-g:none、-g:{lines,vars,source}

  • -g:在生成的class文件中包含所有调试信息(行号、变量、源文件)
  • -g:none :在生成的class文件中不包含任何调试信息。

这个参数在javac编译中是看不到什么作用的,因为调试信息都在class文件中,而我们看不懂这个class文件。

为了看出这个参数的作用,我们在eclipse中进行实验。在eclipse中,我们经常做的事就是“debug”,而在debug的时候,我们会

  • 加入“断点”,这个是靠-g:lines起作用,如果不记录行号,则不能加断点。
  • 在“variables”窗口中查看当前的变量,如下图所示,这是靠-g:vars起作用,否则不能查看变量信息。
  • 在多个文件之间来回调用,比如 A.java的main()方法中调用了B.java的fun()函数,而我想看看程序进入fun()后的状态,这是靠-g:source,如果没有这个参数,则不能查看B.java的源代码。

在eclipse中,假设有一个名为 Test 的项目,则可以"右击Test项目" -> "Properties" -> "Java compiler",进入下图界面。

上面用红色方框圈起来的选项,作用就等价于 -g:vars,-g:lines,-g:source。

下面来做几个试验:

实验一:

  • 实验内容:去掉全部的三个选项。
  • 结论:不能进行调试,因为不能加断点,不能查看当前的变量。

实验二:

  • 实验内容:只去掉第1个选项。
  • 结论:在“variables”窗口中,没有记录任何变量。

实验三:

  • 实验内容:去掉第2个选项。
  • 结论:不能加BreakPoint。

实验四:

  • 实验内容:去掉第3个选项。
  • 结论:如果要查看其它文件,则出现: source not found.

-bootclasspath、-extdirs

-bootclasspath和-extdirs 几乎不需要用的,因为他是用来改变 “引导类”和“扩展类”。

  • 引导类(组成Java平台的类):Java\jdk1.7.0_25\jre\lib\rt.jar等,用-bootclasspath设置。
  • 扩展类:Java\jdk1.7.0_25\jre\lib\ext目录中的文件,用-extdirs设置。
  • 用户自定义类:用-classpath设置。

我们用-verbose编译后出现的“类文件的搜索路径”,就是由上面三个路径组成,如下:

[类文件的搜索路径: C:\Java\jdk1.7.0_25\jre\lib\resources.jar,C:\Java\jdk1.7.0_25
\jre\lib\rt.jar,C:\Java\jdk1.7.0_25\jre\lib\sunrsasign.jar,C:\Java\jdk1.7.0_25\j
re\lib\jsse.jar,C:\Java\jdk1.7.0_25\jre\lib\jce.jar,C:\Java\jdk1.7.0_25\jre\lib\
charsets.jar,C:\Java\jdk1.7.0_25\jre\lib\jfr.jar,C:\Java\jdk1.7.0_25\jre\classes
,C:\Java\jdk1.7.0_25\jre\lib\ext\access-bridge-32.jar,C:\Java\jdk1.7.0_25\jre\li
b\ext\dnsns.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\jaccess.jar,C:\Java\jdk1.7.0_25\
jre\lib\ext\localedata.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\sunec.jar,C:\Java\jdk
1.7.0_25\jre\lib\ext\sunjce_provider.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\sunmsca
pi.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\sunpkcs11.jar,C:\Java\jdk1.7.0_25\jre\lib
\ext\zipfs.jar,..\bin]             //紫色表示引导类和扩展类路径,绿色表示用户定义类路径

如果利用 -bootclasspath 重新定义: javac -bootclasspath src Xxx.java,则会出现下面错误:

致命错误: 在类路径或引导类路径中找不到程序包 java.lang

-sourcepath和-classpath(-cp)

  • -classpath(-cp)指定你依赖的类的class文件的查找位置。在Linux中,用“:”分隔classpath,而在windows中,用“;”分隔。
  • -sourcepath指定你依赖的类的java文件的查找位置。

举个例子,

  1. public class A
  2. {
  3. public static void main(String[] args) {
  4. B b = new B();
  5. b.print();
  6. }
  7. }
  1. public class B
  2. {
  3. public void print()
  4. {
  5. System.out.println("old");
  6. }
  7. }

目录结构如下:

sourcepath          //此处为当前目录
  |-src
    |-com
      |- B.java
    |- A.java
  |-bin
    |- B.class               //是 B.java 编译后的类文件

如果要编译 A.java,则必须要让编译器找到类B的位置,你可以指定B.class的位置,也可以是B.java的位置,也可以同时都存在。

javac -classpath bin src/A.java                            //查找到B.class
javac -sourcepath src/com src/A.java                   //查找到B.java
javac -sourcepath src/com -classpath bin src/A.java    //同时查找到B.class和B.java

如果同时找到了B.class和B.java,则:

  • 如果B.class和B.java内容一致,则遵循B.class。
  • 如果B.class和B.java内容不一致,则遵循B.java,并编译B.java。

以上规则可以通过 -verbose选项看出。

-proc:{none,only}、-procpath、-processor

这三个命令是用来自定义“Annotation Processor”的,即你可以自定义注释,比如@Hello,@First 等,解析这些注释就需要"Annotation Processor"。

  • -processor <CustomProcessor> :自定义注释处理器的类
  • -procpath:注释处理器的查找目录。
  • -proc:only:只运行注释处理器,而不编译源文件。
  • -proc:none:不使用注释处理器,只编译源文件。

任务:自定义一个@HelloWorld 注释,并自定义注释处理器“HelloWorldProcessor”,使得在javac编译时输出:HelloWorld.

第一步:定义 @HelloWorld注释。

  1. public @interface HelloWorld
  2. {
  3. }

第二步:使用@HelloWorld注释。

  1. @HelloWorld
  2. public class Dummy
  3. {
  4. }

第三步:编写注释处理器 HelloWorldProcessor。

  • 必须要继承 AbstractProcessor.
  • 对于process方法,每个Annotation都会调用process()方法一次。
  1. 1 import java.util.Set;
  2. 2 import javax.annotation.processing.*;
  3. 3 import javax.lang.model.SourceVersion;
  4. 4 import javax.lang.model.element.TypeElement;
  5. 5 import javax.tools.Diagnostic;
  6. 6
  7. 7 @SupportedAnnotationTypes("HelloWorld") //注释处理器支持的注释:HelloWorld
  8. 8 @SupportedSourceVersion(SourceVersion.RELEASE_7) //注释处理器支持的JDK版本:7
  9. 9 public class HelloWorldProcessor extends AbstractProcessor { //继承 AbstractProcessor
  10. 10 @Override
  11. 11 public synchronized void init(ProcessingEnvironment processingEnv)
  12. 12 {
  13. 13 super.init(processingEnv);
  14. 14 }
  15. 15
  16. 16 @Override
  17. 17 public boolean process(Set<? extends TypeElement> annotations,
  18. 18 RoundEnvironment roundEnv)
  19. 19 {
  20. 20 if (!roundEnv.processingOver()) {
  21. 21 processingEnv.getMessager().printMessage( //注释处理器的报告
  22. 22 Diagnostic.Kind.NOTE, "Hello World!");
  23. 23 }
  24. 24 return true;
  25. 25 }
  26. 26 }

在命令行中输入:

javac HelloWorldProcessor.java 
javac -processor HelloWorldProcessor *.java

输出:

注: Hello World!

-d

  • d就是 destination,用于指定.class文件的生成目录,在eclipse中,源文件都在src中,编译的class文件都是在bin目录中。

这里我用来实现一下这个功能,假设项目名称为project,此目录为当前目录,且在src/com目录中有一个Main.java文件。‘

  1. package com;
  2. public class Main
  3. {
  4. public static void main(String[] args) {
  5. System.out.println("Hello");
  6. }
  7. }

javac -d bin src/com/Main.java

上面的语句将Main.class生成在bin/com目录下。

-implicit:{none,class}

  • 如果有文件为A.java(其中有类A),且在类A中使用了类B,类B在B.java中,则编译A.java时,默认会自动编译B.java,且生成B.class。
  • implicit:none:不自动生成隐式引用的类文件。
  • implicit:class(默认):自动生成隐式引用的类文件。
  1. public class A
  2. {
  3. public static void main(String[] args) {
  4. B b = new B();
  5. }
  6. }
  1. public class B
  2. {
  3. }

如果使用:

javac -implicit:none A.java

则不会生成 B.class。

-source和-target

  • -source:使用指定版本的JDK编译,比如:-source 1.4表示用JDK1.4的标准编译,如果在源文件中使用了泛型,则用JDK1.4是不能编译通过的。
  • -target:指定生成的class文件要运行在哪个JVM版本,以后实际运行的JVM版本必须要高于这个指定的版本。

javac -source 1.4 Xxx.java

javac -target 1.4 Xxx.java

-encoding

  • 指定源文件的编码格式,如果源文件是UTF-8编码的,而-encoding GBK,则源文件就变成了乱码(特别是有中文时)。

javac -encoding UTF-8 Xxx.java

-deprecation

  • 如果你在源文件中使用了“已过时的API”,则生成详细警告信息。
  1. 1 import java.util.Date;
  2. 2 public class Javac01
  3. 3 {
  4. 4 public static void main(String[] args) {
  5. 5 Date date = new Date(2012,12,12);6 }
  6. 7 }

上面的代码中,第5行使用了过时的API,如果使用 javac Javac01.java 编译,则生成:

注: Javac01.java使用或覆盖了已过时的 API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。

上面的输出并不详细。但是如果使用 javac -deprecation Javac01.java 编译,则:

Javac01.java:5: 警告: [deprecation] Date中的Date(int,int,int)已过时
Date date = new Date(2012,12,12);
                     ^

-verbose

输出详细的编译信息,包括:classpath、加载的类文件信息。

比如,我写了一个最简单的HelloWorld程序,在命令行中输入:

D:\Java>javac -verbose -encoding UTF-8 HelloWorld01.java

输出:

[语法分析开始时间 RegularFileObject[HelloWorld01.java]]
[语法分析已完成, 用时 21 毫秒]
[源文件的搜索路径: .,D:\大三下\编译原理\cup\java-cup-11a.jar,E:\java\jflex\lib\J           //-sourcepath
Flex.jar]
[类文件的搜索路径: C:\Java\jdk1.7.0_25\jre\lib\resources.jar,C:\Java\jdk1.7.0_25      //-classpath、-bootclasspath、-extdirs
\jre\lib\rt.jar,C:\Java\jdk1.7.0_25\jre\lib\sunrsasign.jar,C:\Java\jdk1.7.0_25\j
re\lib\jsse.jar,C:\Java\jdk1.7.0_25\jre\lib\jce.jar,C:\Java\jdk1.7.0_25\jre\lib\
charsets.jar,C:\Java\jdk1.7.0_25\jre\lib\jfr.jar,C:\Java\jdk1.7.0_25\jre\classes
,C:\Java\jdk1.7.0_25\jre\lib\ext\access-bridge-32.jar,C:\Java\jdk1.7.0_25\jre\li
b\ext\dnsns.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\jaccess.jar,C:\Java\jdk1.7.0_25\
jre\lib\ext\localedata.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\sunec.jar,C:\Java\jdk
1.7.0_25\jre\lib\ext\sunjce_provider.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\sunmsca
pi.jar,C:\Java\jdk1.7.0_25\jre\lib\ext\sunpkcs11.jar,C:\Java\jdk1.7.0_25\jre\lib
\ext\zipfs.jar,.,D:\大三下\编译原理\cup\java-cup-11a.jar,E:\java\jflex\lib\JFlex
.jar]
[正在加载ZipFileIndexFileObject[C:\Java\jdk1.7.0_25\lib\ct.sym(META-INF/sym/rt.j
ar/java/lang/Object.class)]]
[正在加载ZipFileIndexFileObject[C:\Java\jdk1.7.0_25\lib\ct.sym(META-INF/sym/rt.j
ar/java/lang/String.class)]]
[正在检查Demo]
[正在加载ZipFileIndexFileObject[C:\Java\jdk1.7.0_25\lib\ct.sym(META-INF/sym/rt.j
ar/java/lang/AutoCloseable.class)]]
[正在加载ZipFileIndexFileObject[C:\Java\jdk1.7.0_25\lib\ct.sym(META-INF/sym/rt.j
ar/java/lang/System.class)]]
[正在加载ZipFileIndexFileObject[C:\Java\jdk1.7.0_25\lib\ct.sym(META-INF/sym/rt.j
ar/java/io/PrintStream.class)]]
[正在加载ZipFileIndexFileObject[C:\Java\jdk1.7.0_25\lib\ct.sym(META-INF/sym/rt.j
ar/java/io/FilterOutputStream.class)]]
[正在加载ZipFileIndexFileObject[C:\Java\jdk1.7.0_25\lib\ct.sym(META-INF/sym/rt.j
ar/java/io/OutputStream.class)]]
[已写入RegularFileObject[Demo.class]]
[共 447 毫秒]

编写一个程序时,比如写了一句:System.out.println("hello"),实际上还需要加载:Object、PrintStream、String等类文件,而上面就显示了加载的全部类文件。

-J <标记>

  • 传递一些信息给 Java Launcher.

javac -J-Xms48m   Xxx.java          //set the startup memory to 48M.

-@<文件名>

如果同时需要编译数量较多的源文件(比如1000个),一个一个编译是不现实的(当然你可以直接 javac *.java ),比较好的方法是:将你想要编译的源文件名都写在一个文件中(比如sourcefiles.txt),其中每行写一个文件名,如下所示:

HelloWorld01.java
HelloWorld02.java
HelloWorld03.java

则使用下面的命令:

javac @sourcefiles.txt

编译这三个源文件。

Reference

[1] http://docs.oracle.com/javase/6/docs/technotes/tools/windows/javac.html[2] http://www.cnblogs.com/JeffChen/archive/2008/01/16/1041783.html[3] Java类查找: http://m.oschina.net/blog/109442[4] The Hacker's Guide to Javac: http://scg.unibe.ch/archive/projects/Erni08b.pdf

作者:xiazdong
出处:http://www.cnblogs.com/xiazdong
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

javac命令的更多相关文章

  1. eclipse中的javac命令与java命令

    一.eclipse的javac命令:当eclipse对.java(源文件)文件进行保存操作时(快捷键ctrl+s),会执行javac命令.见上图,Default output folder(默认输出文 ...

  2. JAVAC 命令详解(转)

    本文来自:http://www.cnblogs.com/JeffChen/archive/2008/01/16/1041783.html 结构 javac [ options ] [ sourcefi ...

  3. Java知识点:javac命令

    javac命令初窥 注:以下红色标记的参数在下文中有所讲解. 用法: javac <options> <source files> 其中, 可能的选项包括:   -g     ...

  4. javac 命令行使用总结

    先给出参考的两个链接,然后再总结: 内容:使用javac 指定编译多个目录下java文件 链接:http://zhidao.baidu.com/link?url=W5ZERu8_ouGD-L_JH0v ...

  5. javac命令详解(下)

    摘自http://blog.csdn.net/hudashi/article/details/7058999 javac命令详解(下)                             -ver ...

  6. javac命令详解(上)

    摘自http://blog.csdn.net/hudashi/article/details/7058998   javac命令详解(上)                             ja ...

  7. JAVAC 命令使用方法

    结构 javac [ options ] [ sourcefiles ] [ @files ] 參数可按随意次序排列. options 命令行选项. sourcefiles 一个或多个要编译的源文件( ...

  8. JAVAC 命令详解

    转自:http://jeffchen.iteye.com/blog/395671 结构 javac [ options ] [ sourcefiles ] [ @files ] 参数可按任意次序排列. ...

  9. JAVA和JAVAC 命令行

    转自:http://www.blogjava.net/pdw2009/archive/2008/06/12/207413.html?opt=admin javac和java命令行中的-classpat ...

随机推荐

  1. 表现层及ASP.NET MVC介绍(二)

    表现层及ASP.NET MVC介绍(二) 最近的更新速度越来越慢,主要是项目上比较忙,封装EasyUi也要花很多时间.不过大家请放心,本系列不会半途夭折,并且代码干货也会持续更新.本文继续介绍表现层和 ...

  2. OpenVPN多实例优化的思考过程

    1.sss 当构建组件之间的关系已经错综复杂到接近于一张全然图的时候,就要换一个思路了,或者你须要重构整个系统,或者你将又一次实现一个. 2.TAP网卡和TUN网卡 2.1.TAP的优势 1.方便组网 ...

  3. [Unity3D]Unity3D游戏开发Android内嵌视图Unity查看

    ---------------------------------------------------------------------------------------------------- ...

  4. 吞吐量(Throughput)、QPS、并发数、响应时间(RT)对系统性能的影响

    首先对吞吐量().QPS.并发数.响应时间(RT)几个概念一直比较模糊,也不知道哪些指标可以较好的衡量系统的性能.今天特意查了些资料做一些记录:首先看一些概念(来自百度百科) 1. 响应时间(RT) ...

  5. C语言库函数大全及应用实例十四

    原文:C语言库函数大全及应用实例十四                                       [编程资料]C语言库函数大全及应用实例十四 函数名: strset 功 能: 将一个串 ...

  6. Android NDK进入发展

    使用互联网有很多javah命令生成一个头文件来完成JNI写,但事实上ADT集成NDK后.点点鼠标就可以了,网上的介绍是非常小懒的方法,在这里,我们主要谈论的懒惰JNI发展. 为ADT组态NDK.请个人 ...

  7. 让低版本的IE浏览器 强制渲染为IE8 或者 以上 浏览器模式

    让低版本的IE浏览器 强制渲染为IE8 或者 以上 浏览器模式 那么就要用下面的方法:让网页兼容ie9 复制代码 代码如下: <!–[if lte IE 8]> <meta http ...

  8. LINUX SCP 远程 文件 复制

    首先,以确保直接两个机器IP可以在每个ping通过 然后使用SCP命令从第一台主机向第二台主机复制文件 scp src chiwei@192.168.8.144:/home/chiwei/mydisk ...

  9. android JBOX2D粒子碰撞的实例,以达到特殊效果

    最近完成动画特效工作的一个发展.的效果,所以传统的三大动画无法满足咱们的需求啦(事实上这不是一个动画效果的议题.事实上有一点点游戏的感觉). 寻找一个粒子系统吧,发现JBox2D比較简单的能满足咱们 ...

  10. 【PLSQL】过程procedure形参和参数

    ************************************************************************   ****原文:blog.csdn.net/clar ...