JVM class加载和执行

Written by 蒋彪 20120427

1.       Class load的流程

加载à验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载

其中初始化由new 命令完成

验证主要是验证字节码的正确性

这边的细节理论性太强,不多说

 

整个流程由class loader完成,class loader是双亲委托,父类上溯load。不多废话。

但是据说OSGI不是这样,OSGI的类加载是网状的,每个bulder一个加载器(怎么做到的?有时间研究研究)

 

一个小例子,两个线程在同时初始化一个class的时候,陷入死锁

public class Test2 {

	static class Aim {
		 static{
			 if(true) {
				System.out.println(Thread.currentThread() + " initing");
				while(true){}
			 }
		}
	}
	
	public static void main(String atgs[]) {
		Runnable test = new Runnable(){

			@Override
			public void run() {
				System.out.println(Thread.currentThread() + " start");
				Aim aim = new Aim();
				System.out.println(Thread.currentThread() + " over");
			}
			
		};
		
		Thread thread1 = new Thread(test);
		Thread thread2 = new Thread(test);
		thread1.start();
		thread2.start();
		
	}
}


 

2.       字节码的执行

字节码加载到JVM里面以后,静态方法签名都被固化了。

但是实际运行的对象引用是运行时链接。

2.1   比如重写

public class ReWriteSample {
	
	static class Human{

		
	}
	static class Boy extends Human {
		
	}

	public static void test(Human human) {
		System.out.println("human");
	}
	
	public static void test(Boy boy) {
		System.out.println("boy");
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Human human = new Human();
		Human boy = new Boy();
		test(human);
		test(boy);
	}

}


 

运行结果是两个human

查看代码编译之后的字节码

public class ReWriteSample extends java.lang.Object
  SourceFile: "ReWriteSample.java"
  InnerClass:
   #50= #40 of #1; //Boy=class ReWriteSample$Boy of class ReWriteSample
   #51= #37 of #1; //Human=class ReWriteSample$Human of class ReWriteSample
  minor version: 0
  major version: 50
  Constant pool:
const #1 = class        #2;     //  ReWriteSample
const #2 = Asciz        ReWriteSample;
const #3 = class        #4;     //  java/lang/Object
const #4 = Asciz        java/lang/Object;
const #5 = Asciz        <init>;
const #6 = Asciz        ()V;
const #7 = Asciz        Code;
const #8 = Method       #3.#9;  //  java/lang/Object."<init>":()V
const #9 = NameAndType  #5:#6;//  "<init>":()V
const #10 = Asciz       LineNumberTable;
const #11 = Asciz       LocalVariableTable;
const #12 = Asciz       this;
const #13 = Asciz       LReWriteSample;;
const #14 = Asciz       test;
const #15 = Asciz       (LReWriteSample$Human;)V;
const #16 = Field       #17.#19;        //  java/lang/System.out:Ljava/io/PrintS
tream;
const #17 = class       #18;    //  java/lang/System
const #18 = Asciz       java/lang/System;
const #19 = NameAndType #20:#21;//  out:Ljava/io/PrintStream;
const #20 = Asciz       out;
const #21 = Asciz       Ljava/io/PrintStream;;
const #22 = String      #23;    //  human
const #23 = Asciz       human;
const #24 = Method      #25.#27;        //  java/io/PrintStream.println:(Ljava/l
ang/String;)V
const #25 = class       #26;    //  java/io/PrintStream
const #26 = Asciz       java/io/PrintStream;
const #27 = NameAndType #28:#29;//  println:(Ljava/lang/String;)V
const #28 = Asciz       println;
const #29 = Asciz       (Ljava/lang/String;)V;
const #30 = Asciz       LReWriteSample$Human;;
const #31 = Asciz       (LReWriteSample$Boy;)V;
const #32 = String      #33;    //  boy
const #33 = Asciz       boy;
const #34 = Asciz       LReWriteSample$Boy;;
const #35 = Asciz       main;
const #36 = Asciz       ([Ljava/lang/String;)V;
const #37 = class       #38;    //  ReWriteSample$Human
const #38 = Asciz       ReWriteSample$Human;
const #39 = Method      #37.#9; //  ReWriteSample$Human."<init>":()V
const #40 = class       #41;    //  ReWriteSample$Boy
const #41 = Asciz       ReWriteSample$Boy;
const #42 = Method      #40.#9; //  ReWriteSample$Boy."<init>":()V
const #43 = Method      #1.#44; //  ReWriteSample.test:(LReWriteSample$Human;)V
const #44 = NameAndType #14:#15;//  test:(LReWriteSample$Human;)V
const #45 = Asciz       args;
const #46 = Asciz       [Ljava/lang/String;;
const #47 = Asciz       SourceFile;
const #48 = Asciz       ReWriteSample.java;
const #49 = Asciz       InnerClasses;
const #50 = Asciz       Boy;
const #51 = Asciz       Human;

{
public ReWriteSample();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable:
   line 2: 0

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      5      0    this       LReWriteSample;


public static void test(ReWriteSample$Human);
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #22; //String human
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   8:   return
  LineNumberTable:
   line 13: 0
   line 14: 8

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      9      0    human       LReWriteSample$Human;


public static void test(ReWriteSample$Boy);
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #32; //String boy
   5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   8:   return
  LineNumberTable:
   line 17: 0
   line 18: 8

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      9      0    boy       LReWriteSample$Boy;


public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=3, Args_size=1
   0:   new     #37; //class ReWriteSample$Human
   3:   dup
   4:   invokespecial   #39; //Method ReWriteSample$Human."<init>":()V
   7:   astore_1
   8:   new     #40; //class ReWriteSample$Boy
   11:  dup
   12:  invokespecial   #42; //Method ReWriteSample$Boy."<init>":()V
   15:  astore_2
   16:  aload_1
//静态调用
   17:  invokestatic    #43; //Method test:(LReWriteSample$Human;)V
   20:  aload_2
   21:  invokestatic    #43; //Method test:(LReWriteSample$Human;)V
   24:  return
  LineNumberTable:
   line 24: 0
   line 25: 8
   line 26: 16
   line 27: 20
   line 28: 24

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      25      0    args       [Ljava/lang/String;
   8      17      1    human       LReWriteSample$Human;
   16      9      2    boy       LReWriteSample$Human;


}


 

2.2   再比如重载

代码稍微改一下

public class ReWriteSample {
	
	static class Human{
		public void SayHello() {
			System.out.println("human");
		}
		
	}
	static class Boy extends Human {
		public void SayHello() {
			System.out.println("boy");
		}
	}

	public static void test(Human human) {
		human.SayHello();
	}
	
	public static void test(Boy boy) {
		boy.SayHello();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Human human = new Human();
		Human boy = new Boy();
		test(human);
		test(boy);
	}

}


 

我们查看字节码

public static void test(ReWriteSample$Human);
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
//虚拟调用,会在运行态沿着继承树查找对象
   1:   invokevirtual   #16; //Method ReWriteSample$Human.SayHello:()V
   4:   return
  LineNumberTable:
   line 17: 0
   line 18: 4

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      5      0    human       LReWriteSample$Human;


public static void test(ReWriteSample$Boy);
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokevirtual   #24; //Method ReWriteSample$Boy.SayHello:()V
   4:   return
  LineNumberTable:
   line 21: 0
   line 22: 4

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      5      0    boy       LReWriteSample$Boy;


 

3.       基于stack的字节码执行引擎

一般来说指令集有基于寄存器和基于栈的。

JVM为了和平台无关性,选用了基于栈的指令集。

比如

/**
	 * @param args
	 */
	public static void main(String[] args) {
		int i =1;
		int j=0;
		int k = (i + j)*j;
		
	}


字节码如下:

 

public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=4, Args_size=1
//第一个参数压栈
   0:   iconst_1
   1:   istore_1
//第二个参数压栈
   2:   iconst_0
   3:   istore_2
//两个参数出栈
   4:   iload_1
   5:   iload_2
//两个参数相加以后保留在变量池中
   6:   iadd
//第三个参数出栈
   7:   iload_2
//相乘
   8:   imul
//压栈,返回
   9:   istore_3
   10:  return
  LineNumberTable:
   line 28: 0
   line 29: 2
   line 30: 4
   line 32: 10

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      11      0    args       [Ljava/lang/String;
   2      9      1    i       I
   4      7      2    j       I
   10      1      3    k       I

}


#以上#

你可能感兴趣的:(jvm,thread,String,Class,osgi,引擎)