Java虚拟机笔记--2

来源:互联网 发布:淘宝网的卖家中心在哪 编辑:程序博客网 时间:2024/06/02 17:19

字段表(field_info)用于描述接口或者类中声明的变量。字段(field)包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。我们可以想一想在Java中描述一个字段可以包含什么信息?可以包括的信息有:字段的作用域(public、private、protected修饰符)、是实例变量还是类变量(static修饰符)、可变性(final)、并发可见性(volatile修饰符,是否强制从主内存读写)、可否被序列化(transient修饰符)、字段数据类型(基本类型、对象、数组)、字段名称。上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫什么名字、字段被定义为什么数据类型,这些都是无法固定的,只能引用常量池中的常量来描述。

从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现[1],是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且
全都继承自抽象类java.lang.ClassLoader。

启动类加载器(Bootstrap ClassLoader):前面已经介绍过,这个类将器负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可,

扩展类加载器(Extension ClassLoader):这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。
应用程序类加载器(Application ClassLoader):这个类加载器由sun.misc.Launcher $App-ClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
我们的应用程序都是由这3种类加载器互相配合进行加载的,如果有必要,还可以加入自己定义的类加载器。

这些类加载器之间的关系一般如图所示。


双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。


public class StaticDispatch {static abstract class Human {}static class Man extends Human {}static class Woman extends Human {}public void sayHello(Human guy) {System.out.println("hello,guy!-- human");}public void sayHello(Man guy) {System.out.println("hello,gentleman!-- man");}public void sayHello(Woman guy) {System.out.println("hello,lady!--woman");}public static void main(String[] args) {Human man = new Man();Human woman = new Woman();StaticDispatch sr = new StaticDispatch();sr.sayHello(man);sr.sayHello(woman);}}

hello,guy!-- humanhello,guy!-- human

代码清单8-7 重载方法匹配优先级

public class Overload {public static void sayHello(Object arg) {System.out.println("hello Object");}public static void sayHello(int arg) {System.out.println("hello int");}public static void sayHello(long arg) {System.out.println("hello long");}public static void sayHello(Character arg) {System.out.println("hello Character");}public static void sayHello(char arg) {System.out.println("hello char");}publicstatic void sayHello(char ...arg){System.out.println("hello char……");}public static void sayHello(Serializable arg) {System.out.println("hello Serializable");}public static void main(String[] args) {sayHello('a');}}

方法动态分派演示

public class DynamicDispatch{static abstract class Human{protected abstract void sayHello();}static class Man extends Human{@Overrideprotected void sayHello(){System.out.println("man say hello");}}static class Woman extends Human{@Overrideprotected void sayHello(){System.out.println("woman say hello");}}public static void main(String[]args){Human man=new Man();Human woman=new Woman();man.sayHello();woman.sayHello();man=new Woman();man.sayHello();}}

单分派和多分派

public class Dispatch{static class QQ{}static class _360{}public static class Father{public void hardChoice(QQ arg){System.out.println("father choose qq");}public void hardChoice( _360 arg){System.out.println("father choose 360");}}public static class Son extends Father{public void hardChoice(QQ arg){System.out.println("son choose qq");}public void hardChoice( _360 arg){System.out.println("son choose 360");}}public static void main(String[]args){Father father=new Father();Father son=new Son();father.hardChoice(new _360());son.hardChoice(new QQ());}}

根据上述论证的结果,我们可以总结一句:今天(直至还未发布的Java 1.8)的Java语言是一门静态多分派、动态单分派的语言。

动态代理的简单示例

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class DynamicProxyTest{interface IHello{void sayHello();}static class Hello implements IHello{@Overridepublic void sayHello(){System.out.println("hello world");}}static class DynamicProxy implements InvocationHandler{Object originalObj;Object bind(Object originalObj){this.originalObj=originalObj;return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy,Method method,Object[]args)throws Throwable{System.out.println("welcome");return method.invoke(originalObj,args);}}public static void main(String[]args){IHello hello=(IHello)new DynamicProxy().bind(new Hello());hello.sayHello();}}