1、有哪些JVM自带类加载器?
根加载器bootstrap:加载虚拟机核心类库,C++代码编写
扩展类加载器:负载加载jre/lib/ext目录下类
系统类加载器:加载classpath下的类库
2、类的实例化顺序
1. 父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行
2. 子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行
3. 父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
4. 父类构造方法
5. 子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
6. 子类构造方法
结论:对象初始化的顺序,先静态方法,再构造方法,每个又是先基类后子类。
3、在自己的代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加
载?为什么。
因加载某个类时,优先使用父类加载器加载需要使用的类。如果我们自定义了java.lang.String这个类,
加载该自定义的String类,该自定义String类使用的加载器是AppClassLoader,根据优先使用父类加载器原理,
AppClassLoader加载器的父类为ExtClassLoader,所以这时加载String使用的类加载器是ExtClassLoader,
但是类加载器ExtClassLoader在jre/lib/ext目录下没有找到String.class类。然后使用ExtClassLoader父类的加载器BootStrap,
父类加载器BootStrap在JRE/lib目录的rt.jar找到了String.class,将其加载到内存中。这就是类加载器的委托机制。
1、反射的原理,反射创建类实例的三种方式是什么。
运行时,反射就是通过字节码文件找到某一个类、类中的方法以及属性等。
创建Class实例三种方式:
1)使用 对象名.class 方法。仅适合在编译前就已经明确要操作的 Class
2)通过类名获取Class对象,Class<T> c = Class.forName("类的完全路径");
3)Class class3 = Person.class;
获取对象实例的方法:
1)Object o = clazz.newInstance();
2)Constroctor constroctor = clazz.getConstructor(String.class,Integer.class); /
// 使用构造器对象的newInstance方法初始化对象
Object obj = constroctor.newInstance("龙哥", 29);
2、反射中,Class.forName和ClassLoader区别
Class.forName 进行加载、链接、初始化,如JDBC驱动加载需要使用此种方式
ClassLoader 仅进行加载,不初始化
3、描述动态代理的几种实现方式,分别说出相应的优缺点
1)JDK原生:对实现了接口的类生成代理,而不能针对类
2)GCLIB:针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final
3)Javassist
4)ASM
JDK原生与GCLIB区别:
一、原理区别:
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
(1)添加CGLIB库,SPRING_HOME/cglib/*.jar
(2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
JDK动态代理和CGLIB字节码生成的区别
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final