jvm,类加载,反射java
Java语言是跨平台语言,一段java代码,通过编译成class文件后,可以在不一样系统的服务器上运行;由于java语言中有虚拟机jvm,才有了跨平台,java为了实现跨平台,在jvm上投入了很大的研发开发资源。jvm是java的底层,本文学习探讨下java的jvm及关联的类加载和反射知识数据库
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是经过在实际的计算机上仿真模拟各类计算机功能来实现的。编程
Java语言的一个很是重要的特色就是与平台的无关性。而使用Java虚拟机是实现这一特色的关键。通常的高级语言若是要在不一样的平台上运行,至少须要编译成不一样的目标代码。而引入Java语言虚拟机后,Java语言在不一样平台上运行时不须要从新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就能够在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。 [1]json
jvm的构成安全
jvm周期:是在java程序执行时运行,程序结束时中止服务器
jvm的基本结构有:类加载子系统、本地方法栈、Java栈、方法区、Java堆、pc寄存器,垃圾回收,执行引擎框架
java是面向对象语言,逻辑代码中的类文件执行逻辑前,是须要jvm读取class文件并校验初始化后才能使用的,包括变量,方法,构造。dom
类加载系统能够认为是在使用到java对像时(抽象),对java对象字节码的读取加载预编译(具体),以后再也不加载(读取校验一次)。jvm
栈是先进后出的结构,java栈时一块线程私有的内存空间,能够理解为一个java线程对应一个java栈,栈和线程密切关联,栈包含线程运行的实时信息,如当前运行方法地址,方法中的瞬时变量等信息ide
在一个jvm实例的内部,类型信息被存储在一个称为方法区的内存逻辑区中。类型信息是由类加载器在类加载时从类文件中提取出来的。类(静态)变量也存储在方法区中。
java堆是和应用程序关系最为密切的内存空间,几乎全部的对象都存放在堆上。而且java堆是彻底自动化管理的,经过垃圾回收机制,垃圾对象会被自动清理,而不须要显示的释放。
存放计算机下一步要执行的指令的地址,
由于程序运行没建立一个对象都须要使用硬件的内存资源,不能无限使用,jvm的垃圾回收可以自动回收再也不使用的java对象,使内存空间有效利用。垃圾回收线程是后台执行的,不须要认为回收内存垃圾,即便有垃圾回收方法调用,但并不能控制jvm如何去将一个对象失效回收。
Java 字节码指令指向特定逻辑得本地机器码,而JVM 解释执行Java字节码指令时,会直接调用字节码指向得本地机器码;
java底层由C语言编写,执行java程序时,jvm每读取一个字节码指令动做,执行引擎就解析解释执行本地系统对应的本地机器码。
虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、转换解析和初始化,最终造成能够被虚拟机直接使用的 Java 类型,这就是虚拟机的类加载机制。
在Java语言里面,类型的加载、链接和初始化过程都是在程序运行期间完成的
做为软件开发语言,java在安全方面也有很高的要求,因此类加载是有一套规则的,jre是java运行时的环境,包括不少基本类,如java.lang.String 是字符串类,这个类很基础也很重要,那在加载的时候不能容许加载的String类被篡改,java保证类加载安全,首先看是否已经加载,若是没有查看核心库是否有此类,没有此类才会去扩展环境找类文件加载,这种机制保证了类在加载时的惟一性和安全性。
java类加载通常来讲是询问本身的parentClassLoader 加载,若是没有加载成功,才本身加载,加载顺序是自上而下
java.lang.ClassLoader 加载类方法
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); //0.是否已加载 if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); //1.没有加载,首先经过父类加载器加载 } else { c = findBootstrapClassOrNull(name); //1.没有父类加载器时加载方式 } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); //若是父类没有加载到类,则使用findClass方法去加载类(这个方法能够重写自定义) // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
反射是Java重要的技术点,在框架开发,AOP切面编程代理等方面都须要反射方面的技术去实现。
Java反射机制主要提供了如下功能:
Class 类的字节码对象
Field 类的属性
Method 类的方法
Constructor 类的构造方法
Annotation 类(方法字段)的注解
模拟事务的注解
@Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface defTransaction { }
普通封装对象
public interface People { String getName(); void setName(String name); Integer getAge(); void setAge(Integer age); BigDecimal getMoney(); void setMoney(BigDecimal money); @defTransaction void addMoney(BigDecimal addNum); @defTransaction void subTractMoney(BigDecimal subNum); }
public class TestPeople implements People{ // 姓名 public String name; // 年龄 private Integer age; // 钱 private BigDecimal money; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public BigDecimal getMoney() { return money; } public void setMoney(BigDecimal money) { this.money = money; } @Override public void addMoney(BigDecimal addNum) { this.money = this.money.add(addNum); } @Override public void subTractMoney(BigDecimal subNum) { this.money = this.money.subtract(subNum); } }
反射测试类
public class ReflectTest { public static void main(String[] args) { // 普通对象建立 使用new People testPeople = new TestPeople(); testPeople.setName("Frank"); testPeople.setAge(18); testPeople.setMoney(new BigDecimal(10)); System.out.println("json:" + JsonUtil.objectToJson(testPeople)); // 反射建立对象 class.newInstance() ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); try { Class<?> clazz = contextClassLoader.loadClass("com.domoment.leaves.common.util.reflect.TestPeople"); if(clazz != null) { Object people = clazz.newInstance(); System.out.println("newInstance start json:" + JsonUtil.objectToJson(people)); // 经过反射执行方法 Method setName = clazz.getMethod("setName", String.class); setName.invoke(people, "inoverFrank"); System.out.println("newInstance end json:" + JsonUtil.objectToJson(people)); } } catch (Exception e) { e.printStackTrace(); } } }
代理类DefProxy (People是被代理类)
public class DefProxy implements InvocationHandler{ // 这个就是咱们要代理的真实对象 private Object subject; // 构造方法,给咱们要代理的真实对象赋初值 public DefProxy(Object subject){ this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Annotation[] annotations = method.getDeclaredAnnotations(); boolean transactionOpen = false; for (Annotation annotation : annotations) { if(annotation instanceof defTransaction) { transactionOpen = true; break; } } if(transactionOpen) { //当方法上有 defTransaction 注解时,执行方法前开启事务 System.out.println("open Transaction"); } System.out.println("proxy:" + method.getName()); Object result = method.invoke(subject, args); if(transactionOpen) { //当方法上有 defTransaction 注解时,执行方法后关闭事务 System.out.println("close Transaction"); } return result; } }
代理测试代码
public class ReflectTest { public static void main(String[] args) { // 反射建立对象 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); try { Class<?> clazz = contextClassLoader.loadClass("com.domoment.leaves.common.util.reflect.TestPeople"); if(clazz != null) { Object people = clazz.newInstance(); System.out.println("newInstance start json:" + JsonUtil.objectToJson(people)); Method setName = clazz.getMethod("setName", String.class); setName.invoke(people, "inoverFrank"); System.out.println("newInstance end json:" + JsonUtil.objectToJson(people)); InvocationHandler handler = new DefProxy(people); // 构造代理对象 People proxyPeople = (People)Proxy. newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler); proxyPeople.setName("proxySetFrank"); proxyPeople.setAge(20); proxyPeople.setMoney(new BigDecimal(999)); System.out.println("proxyPeople end json:" + JsonUtil.objectToJson(people)); proxyPeople.addMoney(new BigDecimal(20)); System.out.println("proxyPeople add json:" + JsonUtil.objectToJson(people)); proxyPeople.subTractMoney(new BigDecimal(17)); System.out.println("proxyPeople end json:" + JsonUtil.objectToJson(people)); } } catch (Exception e) { e.printStackTrace(); } } }
控制台打印
newInstance start json:{} newInstance end json:{"name":"inoverFrank"} proxy:setName proxy:setAge proxy:setMoney proxyPeople end json:{"name":"proxySetFrank","age":20,"money":999} open Transaction proxy:addMoney close Transaction proxyPeople add json:{"name":"proxySetFrank","age":20,"money":1019} open Transaction proxy:subTractMoney close Transaction proxyPeople end json:{"name":"proxySetFrank","age":20,"money":1002}
能够看到方法上有 defTransaction 注解的时候,
方法执行前 打印 open Transaction
方法执行后 打印 close Transaction
这是模拟,真实场景就能够将打印改成代理时扩展方法,如数据库操做时候,开启关闭事务