zoukankan      html  css  js  c++  java
  • cmd中java的编译命令——java和javac、javap

    最近重新复习了一下java基础,这里便讲讲对于一个类文件如何编译、运行、反编译的。也让自己加深一下印象
     

    如题,首先我们在桌面,开始->运行->键入cmd 回车,进入windows命令行。进入如图所示的画面:

    可知,当前默认目录为C盘Users文件夹下的Administrator文件夹。一般而言,我们习惯改变当前目录。由于windows有磁盘分区,若要跳到其他磁盘,例如E盘,有几种方法:

    1、输入命令: pushd 路径(此命令可将当前目录设为所希望的任一个已存在的路径)

    2、输入命令: e: 转移到e盘,然后再输入 cd 转移到所希望的已知路径。

    如图:

    希望在windows命令行下使用javac、java、javap等命令,那么当前电脑必须安装了jdk,并且将jdk的bin目录添加到环境变量path下了。这个不用多说。那么让我们看一下如何使用javac、java、javap吧。

    一、javac

    javac是用来编译.java文件的。命令行下直接输入javac可以看到大量提示信息,提示javac命令的用法,我只知道常用的。

    javac -d destdir srcFile

    其中:1、-d destdir是用来指定存放编译生成的.class文件的路径。(若此选项省略,那么默认在当前目录下生成.class文件,并且没有生成包文件夹;当前目录可以用“.”来表示,即:javac -d . srcFile )

    注意:添加-d选项除了可以指定编译生成的.class文件的路径外,最大的区别是可以将源文件首行的package关键字下的包名在当前路径下生成文件夹。

    2、srcFile是源文件.java文件的路径。

    例如:有这样一个简单的java类,路径为E: estJavacTest.java:

    代码如下:

    package com.stopTalking.test;
    public class JavacTest {
    public static void main(String[] args) {
    byte a = 5;
    short b = 6;
    System.out.println("JavacTest [a=" + a + ", b=" + b + "]");
    }
    }


    当前路径下,输入 javac JavacTest.java ,便在当前路径下生成了一个JavacTest.class的文件,如图:

    注意:JavacTest.java是一个首行标注了package的java文件,而此时它在硬盘上的目录并未对应它的包名,所以,使用java com.stopTalking.test.JavacTest运行时是无法找到该java的。

    若输入,javac –d . JavacTest.java ,那么生成的JavacTest.class便在当前目录下生成的包文件中了,如图:

    二、java

    此时,我们希望运行该类,在大部分的教材中,使用java JavacTest便可直接运行,可是我们发现出现这样的错误:

    这是因为,大部分的教材使用的类是默认包名的,即源文件的第一行是没有package指定包名的。使用一个类,我们知道,是需要使用它的全限定类名的。

    所以,我们在命令行输入:java com/stopTalking/test/JavacTest,便可看到正确的结果了:

    总结:使用简单的java命令运行一个.class文件,不仅需要使用该类的全限定类名,而且需要在当前路径下有该类的包层次文件夹。这必须要求编译时使用-d选项。否则需要自己来建立包层次文件夹。

    三、javap

    javap主要用于帮助开发者深入了解Java编译器的机制,主要选项有:

    -c 分解方法代码,即显示每个方法具体的字节码

    -public | protected | package | private 用于指定显示哪种级别的类成员

    -verbose 指定显示更进一步的详细信息

    输入 javap -c com/stopTalking/test/JavacTest,显示如图:

    **********************************************************

    关于javap的应用(关于java中volatile关键字是否线程安全):

    代码:

    public class VolatileTest{
        
        public static volatile int  i;
    
        public static void increase(){
            i++;
        }
    }

    javap -c -l VolatileTest.class 

    public class VolatileTest {
      public static volatile int i;
     
      public VolatileTest();
        Code:
           0: aload_0       
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return        
        LineNumberTable:
          line 1: 0
     
      public static void increase();
        Code:
           0: getstatic     #2                  // Field i:I, 把i的值取到了操作栈顶,volatile保证了i值此时是正确的. 
           3: iconst_1      
           4: iadd                              // increase,但其他线程此时可能已经把i值加大了好多
           5: putstatic     #2                  // Field i:I ,把这个已经out of date的i值同步回主内存中,i值被破坏了.
           8: return        
        LineNumberTable:
          line 6: 0
          line 7: 8
    }

     观点:

    volatile变量对所有线程是立即可见的,对 volatile变量所有的写操作都能立即反应到

    其他线程之中,换句话说:volatile 变量在各个线程中是一致的,所以基于volatile 变量的运算是线程安全的.  

    这句话论据貌似没有错,论点确实错的.

    但是从使用javap后的字节码来看,volatile 并不完全是线程安全的.(请看第二篇博文)

    http://www.jb51.net/article/48380.htm

    http://www.cnblogs.com/yakun/p/3589437.html

  • 相关阅读:
    LC.225. Implement Stack using Queues(using two queues)
    LC.232. Implement Queue using Stacks(use two stacks)
    sort numbers with two stacks(many duplicates)
    LC.154. Find Minimum in Rotated Sorted Array II
    LC.81. Search in Rotated Sorted Array II
    LC.35.Search Insert Position
    前后端分离:(一)
    Redis基本使用(一)
    GIT篇章(二)
    GIT篇章(一)
  • 原文地址:https://www.cnblogs.com/itommy/p/10610472.html
Copyright © 2011-2022 走看看