Javac is this very well known tool will read the class files, .java, and create bytecode. Very useful and can be used with the following options. I think the -cp and -d
are the most well known options. However, it has some many features we pretty much overlook that I think it is worth considering a second look (some examples from Nam Ha blog).
For instance, there is also the -verbose, example (from my favorite suite of java programs from Univ of Texas):
[fdemeloj@fdemeloj javac]$ javac -version FilterExample.java
javac 1.7.0_171 <------------------------------------------------------ yes, javac is default for JDK 7, use alternatives to fix this
...
[fdemeloj@fdemeloj javac]$ javac -verbose First.java
[parsing started RegularFileObject[First.java]]
[parsing completed 14ms]
[search path for source files: .]
[search path for class files:
...pulse-java.jar,.]
../rt.jar/java/awt/Frame.class)]]
../rt.jar/java/awt/MenuContainer.class)]]
../rt.jar/java/lang/Object.class)]]
../rt.jar/java/awt/Window.class)]]
../rt.jar/javax/accessibility/Accessible.class)]]
../rt.jar/java/awt/Container.class)]]
...
[wrote RegularFileObject[First.class]]
[total 520ms]
[fdemeloj@fdemeloj javac]$ java First
And given a certain directory (already there) you can use -d to set the compiled classes there: javac -d classes, so the .class files will be under /classes dir.
Interestingly -Xdiags:verbose (and compact) options does not seem to add much more on top of the verbose, in fact it adds 0 from when comparing to -verbose option, perhaps depending on the issue it shows more. I mean it helps a lot because it will show what is required vs what was found (see below – Driver class):
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -verbose Driver01.java <--------------------------------------- verbose
[parsing started SimpleFileObject[/home/fdemeloj/Downloads/cases/EJBtests/javac/Driver01.java]]
[parsing completed 29ms]
[loading /modules/java.xml.crypto/module-info.class]
<<several others>>>
...
Driver01.java:41: error: incompatible types: possible lossy conversion from double to int
swap(j, range, enterArray);
^
[total 366ms]
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdiags:compact Driver01.java <----------------------------------- compact
Driver01.java:41: error: incompatible types: possible lossy conversion from double to int
swap(j, range, enterArray);
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdiags:verbose Driver01.java <----------------------------------- verbose
Driver01.java:41: error: method swap in class Driver01 cannot be applied to given types;
swap(j, range, enterArray);
^
required: int,int,double[]
found: double,int,double[]
reason: argument mismatch; possible lossy conversion from double to int
1 error
And some extra options can be found with –help-extra:
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac --help-extra
--add-exports <module>/<package>=<other-module>(,<other-module>)*
Specify a package to be considered as exported from its defining module
to additional modules, or to all unnamed modules if <other-module> is ALL-UNNAMED.
--add-reads <module>=<other-module>(,<other-module>)*
Specify additional modules to be considered as required by a given module.
<other-module> may be ALL-UNNAMED to require the unnamed module.
One the most useful options is actually the Xlint (maybe because of my background in python and python lint process, pep-8 and so forth), I will ended doing a blog post about PMD, Checkstyle, and PetitDej as well:
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xlint First.java
First.java:3: warning: [serial] serializable class First has no definition of serialVersionUID <------
class First extends Frame{
^
1 warning
In JDK 11, interestingly it is possible to set –release flag not only sets source and target versions, but it also causes the compiler to use the symbol table for the JDK libraries corresponding to the specified release. This flag was added after and basically replace –source and –target.
Note: On JDK 11, I think I already mentioned this here that you can just run java, instead of javac, and the class will run:
java Hello.java
Hello, so much snow today in MTL!
I think one of the most useful, which makes javac almost like maven, is the ability to halt the compilation in case a warning happens with -Werror so it makes a default error when it seems a warning:
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdoclint:all -Werror First.java
First.java:3: warning: no comment
class First extends Frame{
^
First.java:5: warning: no comment
First(){
^
First.java:15: warning: no comment
public static void main(String args[]){
^
error: warnings found and -Werror specified
1 error <--------------------------------------------------------------------------- 1 error
3 warnings <------------------------------------------------------------------------ 3 warnings
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdoclint:all First.java
First.java:3: warning: no comment
class First extends Frame{
^
First.java:5: warning: no comment
First(){
^
First.java:15: warning: no comment
public static void main(String args[]){
^
3 warnings <--------------------------------------------------------------------------- 3 warnings