javac : 编译代码(即将.java文件编译成.class的中立字节码文件) eg:javac App.java

  javap是jdk自带的反解析工具。它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。

 -help  --help  -?        输出此用法消息
 -c                       对代码进行反汇编
 -constants               显示静态最终常量
 -l                       输出行号和本地变量表
 -v  -verbose             输出附加信息(包括行号、本地变量表,反汇编等详细信息)
 -version                 版本信息,其实是当前javap所在jdk的版本信息,不是class在哪个jdk下生成的。

java源代码:

package myproject;

public class App
{
    public static void main( String[] args )
    {
      App app=new App();
      int result=app.count(4);
      System.out.println(result);
    }

    public int count(int a){
        int b=3;
        int c=a+b;
        return c;
    }
}

在App.java目录中执行javac App.java 进行编译,生成App.class

然后执行: javap -v App生成如下内容

警告: 二进制文件App包含myproject.App
Classfile /D:/project/Sample/src/main/java/myproject/App.class
  Last modified 2019-9-8; size 492 bytes
  MD5 checksum ab5ebd975fe3cab41580ef51c90d8389
  Compiled from "App.java"
public class myproject.App
  SourceFile: "App.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool: //常量池
   #1 = Methodref          #7.#18         //  java/lang/Object."<init>":()V
   #2 = Class              #19            //  myproject/App
   #3 = Methodref          #2.#18         //  myproject/App."<init>":()V
   #4 = Methodref          #2.#20         //  myproject/App.count:(I)I
   #5 = Fieldref           #21.#22        //  java/lang/System.out:Ljava/io/PrintStream;
   #6 = Methodref          #23.#24        //  java/io/PrintStream.println:(I)V
   #7 = Class              #25            //  java/lang/Object
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               main
  #13 = Utf8               ([Ljava/lang/String;)V
  #14 = Utf8               count
  #15 = Utf8               (I)I
  #16 = Utf8               SourceFile
  #17 = Utf8               App.java
  #18 = NameAndType        #8:#9          //  "<init>":()V
  #19 = Utf8               myproject/App
  #20 = NameAndType        #14:#15        //  count:(I)I
  #21 = Class              #26            //  java/lang/System
  #22 = NameAndType        #27:#28        //  out:Ljava/io/PrintStream;
  #23 = Class              #29            //  java/io/PrintStream
  #24 = NameAndType        #30:#31        //  println:(I)V
  #25 = Utf8               java/lang/Object
  #26 = Utf8               java/lang/System
  #27 = Utf8               out
  #28 = Utf8               Ljava/io/PrintStream;
  #29 = Utf8               java/io/PrintStream
  #30 = Utf8               println
  #31 = Utf8               (I)V
{
  public myproject.App();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 7: 0

  public static void main(java.lang.String[]);//【main方法】
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #2                  // class myproject/App
         3: dup    //[复制上一步创建的对象的引用压入栈]
         4: invokespecial #3                  // Method "<init>":()V 【调用当前的init方法】
         7: astore_1
         8: aload_1
         9: iconst_4
        10: invokevirtual #4                  // Method count:(I)I  【调用count方法】
        13: istore_2
        14: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        17: iload_2
        18: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
        21: return
      LineNumberTable:
        line 11: 0
        line 12: 8
        line 13: 14
        line 14: 21

  public int count(int);
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=2
         0: iconst_3
         1: istore_2
         2: iload_1
         3: iload_2
         4: iadd
         5: istore_3
         6: iload_3
         7: ireturn
      LineNumberTable:
        line 17: 0
        line 18: 2
        line 19: 6
}

   常量池(Constant pool):实际上分为两种形态:静态常量池运行时常量池

静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。这种常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic References),字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等,符号引用则属于编译原理方面的概念,包括了如下三种类型的常量:

    • 类和接口的全限定名
    • 字段名称和描述符
    • 方法名称和描述符

运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

 

  方法区:JVM执行时候会将class加载到方法区,在JDK1.8中方法区已经不存在,原方法区中存储的类信息、编译后的代码数据等已经移动到了元空间。对于创建的对象会分配到内存堆中;其中方法区和内存堆都是线程共享;

  程序计数器:在操作系统调用线程时候,每一个线程都包含一个程序计数器用来保存当前线程执行的位置,方便下次继续往下执行;

 

 

 

 

  :当一个新的线程创建时,JVM会为这个线程创建一个新的Stack。一个Java Stack在一个个独立的栈帧中存储了线程的状态。

  栈帧:当一个线程执行一个Java方法时,JVM将创建一个新的栈帧并且把它push到栈顶。此时新的栈帧就变成了当前栈帧,方法执行时,使用栈帧来存储参数、局部变量、中间指令以及其他数据。

  堆:堆内存主要用于存放对象和数组,它是JVM管理的内存中最大的一块区域,堆内存和方法区都被所有线程共享,在虚拟机启动时创建。

   在垃圾收集的层面上来看,由于现在收集器基本上都采用分代收集算法,因此堆还可以分为新生代(YoungGeneration)和老年代(OldGeneration),新生代还可以分为Eden、From Survivor、To Survivor。

 

volatile

1、可见性  修饰的变量如果是对象或数组之类的,其含义是对象获数组的地址具有可见性,但是数组或对象内部的成员改变不具备可见性:

2、顺序性

3、不具备原子性

 

参考:JVM知识点精华汇总

 

查看内存对象工具:jol 

posted on 2019-09-08 08:49  gudicao  阅读(170)  评论(0编辑  收藏  举报