Java JVM生命周期、动态代理——Java JVM筑基


虚拟机启动

Java虚拟机的启动通过引导类加载器bootstrap class loader,创建一个初始类initial class来完成的,这个类由Java虚拟机具体实现指定。


虚拟机的执行

  • 一个运行的Java虚拟机有一个非常清晰的任务:执行Java程序
  • 程序开始执行虚拟机才会运行,程序结束虚拟机结束。
  • 执行一个所谓的Java程序的时候,真真正正执行的是一个叫做Java虚拟机的进程。

虚拟机的退出

如下情况:

  • 程序正常执行并且结束。
  • 程序执行过程遇到了exception或者error从而异常终止。
  • 由于OS系统调用出现错误导致Java虚拟机进程终止。
  • 线程调用runntime或者system类方法的exit方法,或者Runntime类的halt方法,并且Java安全管理器允许这次exit或者halt操作。
  • 除上述情况之外,JNI规范描述了JNI invocation API加载或者卸载Java虚拟机时,Java虚拟机退出的情况。

Java对象头

在JVM中,对象在内存中的布局分为三部分:对象头、实例数据和对齐填充
在这里插入图片描述

synchronized同步锁就是存储在Java对象头里面的。

Java虚拟机HotSpot有两种对象头:

  • 数组类型,若对象是数组类型,则虚拟机时3个字节宽度(Word)存储对象头。
  • 非数组类型,若对象是非数组类型,则2个word字宽存储对象头。

对象头由两个部分构成:

  • MarkWord:存储自身的运行时数据,例如HashCode、GC年龄,锁相关信息。
  • KlassPointer:类型指针指向了它的类元数据指针。

64位虚拟机的MarkWord是64bit,运行期间,MarkWord存储的数据会随着锁标志位变化而变化。

在这里插入图片描述


Dalvik VM

Google开发的应用于Android系统,并且提供了JIT,发展迅猛。
Dalvik只能称为虚拟机,不可以被叫做Java虚拟机,因为其没有遵循Java虚拟机规范,不可以直接执行Java的class文件。

基于寄存器架构,不是JVM的栈结构。

执行的是编译之后dex文件,执行效率高:

  • 其执行的dex文件可以通过class文件转换而来,使用Java语法编写的app,可以直接使用大部分的Java API等等。

Android 5.0支持提前编译AOT的ART VM替换Dalvik VM。


类加载子系统

概述

在这里插入图片描述

在这里插入图片描述

若想要手写JVM虚拟机,则需要考虑如下两点:

  • 类加载器
  • 执行引擎

类加载器子系统的作用意义

类加载器子系统负责从文件或者网络加载class文件,class文件在文件开头有特定的文件标识。

classLoader只负责class文件的加载,至于是否可执行,则是由Exceution Engine来决定。

加载的信息存放于一块称之为方法区的内存空间,至于是否可运行。除了类信息之外,方法区存放运行时候的常量池信息。可能包括字符串字面常量和数字常量(这部分常量信息是Class文件常量池部分的内存映射)。
在这里插入图片描述

  • classFile存放于本地硬盘,可以当作图纸模板,该模板在执行的时候加载到JVM当中根据该文件实例化出N个一摸一样的实例。
  • classFile加载到JVM中,称之为DNA元数据模板,存放于方法区。
  • 在.class文件 ==> JVM ==> 最终成为一个元数据模板,这个过程需要一个运输的工具,也就是类加载器,扮演快递的角色任务。

在这里插入图片描述


类加载的过程

给出简单代码:

public class Loader {
	public static void main(String[] args) {
		System.out.println("I have been class loader");
	}
}

类加载过程如图所示:

在这里插入图片描述


加载阶段

通过一个类的全限定名称获取该类的二进制字节流。

把该字节流所代表的静态存储结构转换为方法区的运行时数据结构。

内存中生成一个代表该类的java.lang.class对象,并且作为该方法区的各种数据访问入口。


加载class文件的方式

  • 本地系统直接加载。
  • 网络获取,例如:Web applet
  • zip压缩包读取,成为日后jar、war格式的基础。
  • 运行时计算生成,例如:动态代理技术
  • 其他文件生成,典型场景:JSP应用从专有的数据库中提取.class文件
  • 加密文件获取,典型的防止class文件被反编译的保护措施。

补充:代理模式

代理模式:给某一个对象提供一个代理,并由代理对象负责控制真实对象的访问。代理模式是一种结构型设计模式

代理模式角色分为三种:

  • Subject抽象主题角色:定义代理类和真是主题的公共对外方法,也就是代理类的真实主题的方法。
  • RealSubject真实主题角色:真正意义上实现业务逻辑的类。
  • Porxy代理主题角色:用来代理和封装真实的主题。

代理模式结构简单,核心在于代理类,为了实现让客户端实现一致性对待真实对象和代理对象,在代理模式中引入了抽象层。

在这里插入图片描述

代理模式按照指责分类,如下所示:

  • 远程代理。
  • 虚拟代理。
  • Copy-On-Write代理。
  • 保护Protect or Access代理。
  • 同步化synchronized代理。
  • 智能引用Smart Reference代理。

根据字节码class创建时机分类,可以分为静态代理和动态代理:

  • 所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题角色的关系在运行前就确定了。
  • 动态代理就是源码是在程序运行期间由JVM根据反射机制等动态生成,运行前不存在所谓的代理类字节码文件。

代理实例

给出Girl接口:

package proxyTest;

public interface Girl {
	void date();

	void watchMovie();
}

给出实现接口方法:

package proxyTest;

import java.text.SimpleDateFormat;
import java.util.Date;

public class wang implements Girl {

	@Override
	public void date() {
		// TODO Auto-generated method stub
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
		Date date = new Date(System.currentTimeMillis());
		System.out.println("约会日期: " + format.format(date));
	}

	@Override
	public void watchMovie() {
		// TODO Auto-generated method stub
		System.out.println("lets got to watching movie!!!");
	}
}

给出继承invocation的wangProxy:

package proxyTest;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class wangProxy implements InvocationHandler {

	private Girl girl;

	/**
	 * @Title: wangProxy
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param: @param girl
	 * @author: mac
	 * @throws
	 */
	public wangProxy(Girl girl) {
		super();
		this.girl = girl;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		doSomeThingBefore();
		Object obj = method.invoke(girl, args);
		doSomeThingEnd();
		return obj;
	}

	private void doSomeThingEnd() {
		// TODO Auto-generated method stub
		System.out.println("your bill is allright, you can enjoy your movie now!");
	}

	private void doSomeThingBefore() {
		// TODO Auto-generated method stub
		System.out.println("before start watch, we need to check your bill");
	}

	public Object getProxyInstance() {
		return Proxy.newProxyInstance(girl.getClass().getClassLoader(), girl.getClass().getInterfaces(), this);
	}
}

给出main实现代理:

package proxyTest;

public class ListenWang {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 隔壁有个女孩
		Girl girl = new wang();
		// 通过代理实现访问
		wangProxy family = new wangProxy(girl);
		Girl friend = (Girl) family.getProxyInstance();
		// 实现方法
		friend.date();
		System.out.println("=======================");
		friend.watchMovie();
	}
}

运行结果:

before start watch, we need to check your bill
约会日期: 2022-08-22 at 16:17:13 CST
your bill is allright, you can enjoy your movie now!
=================================================
before start watch, we need to check your bill
lets got to watching movie!!!
your bill is allright, you can enjoy your movie now!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值