Java热更新


一、  解决方案

1)  自定义类加载器。

首先需要明白一点,class相等的判断条件不仅仅是类名相同,还需要加载它的ClassLoader相同。JVM内部规定一个ClassLoader不可以重复定义类,也就是说想要重定义一个类,就必须使用一个全新的ClassLoader。

JVM内部class被卸载的条件及其苛刻,甚至没有明确的方法可以直接调用,只有当加载该类型的类加载器实例为unreachable状态时,也就是没有任何实例,class才有可能被卸载。(启动类加载器实例永远为reachable状态,由启动类加载器加载的类型可能永远不会被卸载)

<span style="white-space:pre">	</span>public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
		Class<?> clazz = null;
		// 首先检查请求的类型是否已经被这个类装载器装载到命名空间中了,如果已经装载,直接返回;否则继续。
		if (name.startsWith("com.wafer") || name.contains("Service")) {
			if (resolve) {
				resolveClass(clazz); // 链接指定的 Java 类
			}
			// 如果class类被修改过,则重新加载
			MoeLoader hcl = new MoeLoader(url);
			clazz = customLoad(name, hcl);
			return (clazz);
		}
		// 如果类的包名为"java."开始,则有系统默认加载器加载
		try {
			// 得到系统默认的加载cl
			ClassLoader system = ClassLoader.getSystemClassLoader();
			clazz = system.loadClass(name); // 加载名称为 name的类
			if (clazz != null) {
				if (resolve)
					resolveClass(clazz);
				return (clazz);
			}
		} catch (ClassNotFoundException e) {
			// Ignore
		}
		return customLoad(name, this);
	}

此范例的核心在于缓存自己已经加载的class,当再次需要加载时,如果发生变更,则可以new一个ClassLoader,这样新的字节码便可以即时生效。

JRbel是一种热更新的方案,它实现的方式是通过在启动参数中添加javaagent,即JVM底层提供的Instrumentation技术,来改变生成对象的方式。

2)  JVMTI虚拟机工具接口

JPDA是 Java 平台调试体系结构的缩写。通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。 JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI)、Java 调试线协议(JDWP),以及 Java 调试接口(JDI)。参考资源(http://www.ibm.com/developerworks/cn/views/java/libraryview.jsp?search_by=深入+Java+调试体系)

<span style="white-space:pre">	</span>List<Connector> connectors =    Bootstrap.virtualMachineManager().allConnectors();
		SocketAttachingConnector sac = null;
		for (Connector connector : connectors) {
			if (connector instanceof SocketAttachingConnector) {
				sac = (SocketAttachingConnector) connector;
			}
		}
		if (sac != null) {
			Map<String, Connector.Argument> defaultArguments = sac.defaultArguments();
			Connector.Argument hostArg = defaultArguments.get("hostname");
			Connector.Argument portArg = defaultArguments.get("port");
			hostArg.setValue("localhost");
			portArg.setValue("8787");
			VirtualMachine vm = sac.attach(defaultArguments);

			List<ReferenceType> rtList = vm.classesByName("com.wafer.demo.jdi.Foo");
			ReferenceType rt = rtList.get(0);
			Map<ReferenceType, byte[]> newByteCodeMap = new HashMap<ReferenceType, byte[]>(1);
			//获取特定类的字节码,发送到虚拟机
			byte[] newByteCode = genNewByteCodeUsingJavassist();
			newByteCodeMap.put(rt, newByteCode);

			if (vm.canRedefineClasses()) {
				vm.redefineClasses(newByteCodeMap);
			}
		}

Eclipse的热更新实现的方式便是如此,以Debug启动时,Eclipse会在JVM参数中添加-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:63597,之后检测到代码变更时,将变更的字节码通过jdwp发送到应用。

BTrace可以发送字节码到应用,对拦截的类进行监控,其实现的方式同样用到JVMTI。使用VirtualMachine.attach(pid)连接到应用。

时间: 2024-11-01 11:38:24

Java热更新的相关文章

移动端热更新方案(iOS+Android)

PPT资源包含iOS+Android 各种方案分析:https://github.com/qiyer/Share/blob/master/%E7%83%AD%E6%9B%B4%E6%96%B0%E5%88%86%E4%BA%ABPPT.pptx 一 .热更新(热修复)产品背景 这里谈到的热更新都是指APP(不包含网页).APP按大类别可以粗略分为 应用 和 游戏.APP的开发周期是极其快速的,在实际开发流程中,我们总会有一些需求迫使我们短时间内快速上线,比如需求流程出错,程序员主观导致的一些bu

ionic2新手入门整理,搭建环境,创建demo,打包apk,热更新,优化启动慢等避坑详解

onic官方文档链接:http://ionicframework.com/docs/ 如果是新的环境会有很多坑,主要是有墙,请仔细阅读每个步骤 文档包含以下内容: l  环境搭建 l  创建demo并调试运行 l  打包APK l  添加支持热更新 l  优化启动慢问题 l  常用命令 1.      环境搭建 需要安装以下软件和插件(Android): l  安装nodeJS(自带npm) l  配置cnpm  (使用淘宝镜像取代npm) l  安装cordova和ionic2 l  安装JA

苹果下架4万App就只是因为“热更新”

前去除软件热更新功能,不然有可能下架后,昨日(6 月 22 日),有媒体报道,一周内苹果 App Store 下架了近 4万款中国 App .一种流行观点认为,苹果不是说着玩,而是真对热更新动刀子了. 热更新是一种各大手游等众多 App 常用的更新方式,即用户通过 App Store下载App之后,打开 App 时遇到的即时更新. 2017年6月,AppStore 审核团队确实针对 AppStore 中"热更新"的 App 开发者发送邮件,要求移除所有相关的代码.框架或 SDK,并重新

我使用的 unity 热更新方案 JSB(求小编 推荐一下)

今天周五 ,明天没有什么事情,可以安心写一些博客. 今天聊 两个话题 一 , unity热更新的窘境 二 ,我所使用的unity 热更新方案JSB ======================================热更新的窘境============================================= (1)其实unity 热更新到瓶颈是 ios 的 系统本身 ,禁止你 jit .说白了,内存中代码,系统本身不让你执行. 安卓 系统,桌面 系统,本身都支持 动态直接替换d

Android 热更新——非侵入AOP框架

Android 客户端应用上线以后,一旦出现Bug,一般的解决思路是发修复包升级应用,这种方式不仅耗时,更重要的是用户需要频繁的升级版本,体验不好,所以优化的思路是在不发版本的情况下热更新,以期提高用户体验. 近期GitHub新出一种非侵入运行期AOP框架Dexposed, 下面简单了解一下这个框架,GitHub地址. 简要说明: 该框架基于AOP思想,支持经典的AOP使用场景,可应用于日志记录,性能统计,安全控制,事务处理,异常处理等方面. 针对Android平台,Dexposed支持函数级别

Android热更新开源项目Tinker集成实践总结

前言 最近项目集成了Tinker,开始认为集成会比较简单,但是在实际操作的过程中还是遇到了一些问题,本文就会介绍在集成过程大家基本会遇到的主要问题. 考虑一:后台的选取 目前后台功能可以通过三种方式实现: 1.自己搭建后台布丁下发系统2.第三方提供的服务,目前如原微信simsun大神的个人tinkerpatch平台,目前出于内测阶段,暂时免费.后期应该会按下发量对app进行收费.3.腾讯Bugly提供的服务,提供了热更新的下发后台,集成到了bugly的升级sdk中.免费.根据公司的精神,我们选择

Android 热更新是如何实现的?

Android开发中,我们常常遇到热更新这个概念,而这个热更新具体是怎么实现的呢?今天在网上看到一个大神分享的热更新相关实现原理和实现代码,感觉灰常不错,分享给广大码农盆友look look . ClassLoader Android的基础语言是Java,而Java在运行时加载对应的类是通过ClassLoader来实现的,ClassLoader本身是一个抽象来,Android中使用PathClassLoader类作为Android的默认的类加载器. PathClassLoader又是什么?Pat

Spring-Loaded实现热更新

1.简介 Spring-Loaded是基于javaAgent实现的一个代理,更多javaAgent可以参考: java代理-javassist:http://my.oschina.net/OutOfMemory/blog/309283 官网:https://github.com/spring-projects/spring-loaded 当前的最新版:1.2.4.RELEASE 2.说明 目前最新版1.2.4.RELEASE实现了监听jar包的更新的机制,实现热更新jar包,目前官方提供的版本在

React Native之code-push的热更新(ios android)

React Native之code-push的热更新(ios android) React Native支持大家用React Native技术开发APP,并打包生成一个APP.在动态更新方面React Native只是提供了动态更新的基础,对将应用部署到哪里,如何进行动态更新并没有支持的那么完善.好在微软开发了CodePush,填补React Native 应用在动态更新方面的空白.CodePush 是微软提供的一套用于热更新 React Native 和 Cordova 应用的服务.下面将向大