(從csdn的blog轉來)?

Java 程序的工作機制: Java 對象都以單獨的 class 文件存在, java 虛擬機將其載入并執行其虛擬機指令。

?

Java 虛擬機查找這些 java 對象:

java 虛擬機根據 class path 來查找 java 對象,而虛擬機的 class path 又分為三層:

bootstrap sun.boot.class.path

extension: java.ext.dirs

application: java.class.path

三個 class path 各有對應的 classloader 。由上而下形成父子關系

當程序中調用 new 指令,或者 ClassLoader.load 方法時。其順序如下:

1.?????? 首先查看 application classloader 中是否已有對應的 class 緩存,如果有則返回,并根據 class 分配內存。如果沒有,接下一步。

2.?????? 首先查看 extension classloader 中是否已有對應的 class 緩存,如果有則返回,并根據 class 分配內存。如果沒有,接下一步。

3.?????? 首先查看 bootstrap classloader 中是否已有對應的 class 緩存,如果有則返回,并根據 class 分配內存。如果沒有,接下一步。

4.?????? bootstrap classloader 在其 class path 中試圖加載該 class ,如果有,則將該 class 放入 cache 中,并返回。如果沒有,接下一步。

5.?????? extension classloader 在其 class path 中試圖加載該 class ,如果有,則將該 class 放入 cache 中,并返回。如果沒有,接下一步。

6.?????? application classloader 在其 class path 中試圖加載該 class ,如果有,則將該 class 放入 cache 中,并返回。如果沒有,則拋出 ClassNotFound exception

?

Java 虛擬機加載這些 java 對象:

每個 java 虛擬機都在其啟動時產生一個唯一的 class heap ,并把所有的 class instance 都分配在其中。其中每個類實例的信息又分兩部分, fields 域和 methods 域。每個類實例各自擁有 fields ,但同一個類的不同實例共享 methods

?

反射

JVM 對反射的處理

簡單例子代碼:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.InvocationTargetException;

import java.io.IOException;

?

public class Main {

??? public static void main(String[] args){

??????? TempImpl t1 = new TempImpl("temp1");

??????? try {

??????????? Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ;

??????????? t1Talk.invoke(t1, null);

??????? } catch (NoSuchMethodException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? } catch (IllegalAccessException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? } catch (InvocationTargetException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? }

??????? try {

??????????? System.in.read();

??????? } catch (IOException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? }

??? }

}

復雜例子代碼:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.InvocationTargetException;

import java.io.IOException;

?

public class Main {

??? public static void main(String[] args){

??????? TempImpl t1 = new TempImpl("temp1");

??????? TempImpl t2 = new TempImpl("temp2");

??????? Temp2 temp2 = new Temp2();

??????? try {

??????????? Method t1Talk = t1.getClass().getMethod("Talk", new Class[0]) ;

??????????? Method t2Talk = t2.getClass().getMethod("Talk", new Class[0]) ;

??????????? t1Talk.invoke(t2, null);

??????????? t2Talk.invoke(t1, null);

??????????? if(t1Talk.equals(t2Talk)){

??????????????? System.out.println("equals");

??????????? }

?????????? else{

??????????????? System.out.println("not equals");

?????? ?????}

??????????? if(t1Talk==t2Talk){

??????????????? System.out.println("ref equals");

??????????? }

?????????? else{

??????????????? System.out.println("ref not equals");

??????????? }

??????????? t2Talk.invoke(temp2, null);

??????? } catch (NoSuchMethodException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? } catch (IllegalAccessException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? } catch (InvocationTargetException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? }

??????? try {

??????????? System.in.read();

??????? } catch (IOException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? }

??? }

}

?

分析: java 虛擬機把每個 methods 當作一個執行單元。該執行單元帶有兩種簽名:類簽名和屬性簽名( public static 等)。 反射的第一步,驗證簽名的合法性。驗證通過后,順序執行該 method 中的指令,當需要訪問類實例的 fields 和傳入參數時,由虛擬機注入。

?

動態代理

Sun 對動態代理的說明:

一個簡單例子代碼:

動態代理的內部實現——代碼生成:

研究 JDK 源代碼,發現在 Proxy sun 實現中調用了 sun.misc.ProxyGenerator 類的 generateProxyClass( proxyName, interfaces) 方法,其返回值為 byte[] class 文件的內存類型一致。于是做如下試驗:

public class? ProxyClassFile{

?????? public static void main(String[] args){

????????????? String proxyName = "TempProxy";

??????? TempImpl t = new TempImpl("proxy");

????????????? Class[] interfaces =t.getClass().getInterfaces();

?????????????

????????????? byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

????????????? ??? proxyName, interfaces);

??????? File f = new File("classes/TempProxy.class");

??????? try {

??????????? FileOutputStream fos = new FileOutputStream(f);

??????????? fos.write(proxyClassFile);

??????????? fos.flush();

??????????? fos.close();

??????? } catch (FileNotFoundException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? } catch (IOException e) {

??????????? e.printStackTrace();? //To change body of catch statement use File | Settings | File Templates.

??????? }

?????? }

}

運行該類,到 class 文件夾下,利用反編譯技術,發現原來其采用了代碼生產技術:

?

public interface Temp{

?????? public void Talk();

?????? public void Run();

}

import java.lang.reflect.*;

?

public final class TempProxy extends Proxy

??? implements Temp{

?

??? private static Method m4;

??? private static Method m2;

??? private static Method m0;

??? private static Method m3;

??? private static Method m1;

?

??? public TempProxy(InvocationHandler invocationhandler)?? {

??????? super(invocationhandler);

??? }

?

??? public final void Run()??? {

??????? try {

??????????? h.invoke(this, m4, null);

??????????? return;

??????? }

??????? catch(Error _ex) { }

??????? catch(Throwable throwable)? {

??????????? throw new UndeclaredThrowableException(throwable);

??????? }

??? }

?

??? public final String toString(){

??????? try{

??????????? return (String)h.invoke(this, m2, null);

??????? }

??????? catch(Error _ex) { }

??????? catch(Throwable throwable) ?{

??????????? throw new UndeclaredThrowableException(throwable);

??????? }

??????? return "";

??? }

?

??? public final int hashCode() {

??????? try {

??????????? return ((Integer)h.invoke(this, m0, null)).intValue();

??????? }

??????? catch(Error _ex) { }

??????? catch(Throwable throwable){

??????????? throw new UndeclaredThrowableException(throwable);

??????? }

??????? return 123;

??? }

?

??? public final void Talk(){

??????? try{

??????????? h.invoke(this, m3, null);

??????????? return;

??????? }

??????? catch(Error _ex) { }

??????? catch(Throwable throwable) {

??????????? throw new UndeclaredThrowableException(throwable);

??????? }

??? }

?

??? public final boolean equals(Object obj) {

??????? try? {

??????????? return ((Boolean)h.invoke(this, m1, new Object[] {

??????????????? obj

??????????? })).booleanValue();

??????? }

??????? catch(Error _ex) { }

??????? catch(Throwable throwable) {

??????????? throw new UndeclaredThrowableException(throwable);

??????? }

??????? return false;

??? }

?

??? static{

??????? try{

???? m4 = Class.forName("Temp").getMethod("Run", new Class[0]);

???? m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);

??? ?m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);

??? ?m3 = Class.forName("Temp").getMethod("Talk", new Class[0]);

???? m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {

??????????????? Class.forName("java.lang.Object")

??????????? });

??????? }

??????? catch(NoSuchMethodException nosuchmethodexception) {

? ??????????throw new NoSuchMethodError(nosuchmethodexception.getMessage());

??????? }

??????? catch(ClassNotFoundException classnotfoundexception) {

??????????? throw new NoClassDefFoundError(classnotfoundexception.getMessage());

??????? }

??? }

}

?

?