为了账号安全,请及时绑定邮箱和手机立即绑定

优雅的给线上环境打补丁

标签:
Java

场景

在线上往往会遇到一些比较尴尬的异常,例如空指针。这种操作往往是某些情况校验不完善,客户输入了各种奇怪的内容导致的。当遇到这种情况的时候,修改都很方便,但是如何更新到线上是个问题了。为一个小问题,重新更换环境就动作有点大了,还得晚上派人值守。

更新方式

我们主要利用了2中java的外挂技术来完成这种不重启更新环境。这两种技术分别是javaagent以及 Vitural Machine attach。attach主要是为了把javaagent给attach到目标进程上。javaagent里主要写类的重新转化工作。

public class Transform implements ClassFileTransformer {

	@Override
	public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
			ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

		if (className.contains(Main.CLASS_NAME)) {//过滤类
			byte[] readAllBytes = null;
			try {
			//读取修改后的字节码
				readAllBytes = Files.readAllBytes(Paths.get("E:\\delete\\Nep.class"));
			} catch (IOException e) {
				e.printStackTrace();
			}
			return readAllBytes;
		}
		return null;
	}

}

当类加载或者重新转化的时候会经过ClassFileTransformer的 transform方法,返回null表示字节码没有任何修改,如果返回一个新的数组,就可以替换加载到内存的字节码了。

	public static void agentmain(String args, Instrumentation ins) throws UnmodifiableClassException {
		//第二个参数表示是否能重新定义
		ins.addTransformer(new Transform(), true);
		List<Class> transformClass =new ArrayList<Class>();
		Class[] allLoadedClasses = ins.getAllLoadedClasses();
		for (Class clazz : allLoadedClasses) {
			if (clazz.getName() != null && clazz.getName().contains(CLASS_NAME)) {
				transformClass.add(clazz);
			}
		}
		if(!transformClass.isEmpty()){
			ins.retransformClasses(transformClass.toArray(new Class[0]));
		}
}

agentmain是一个入口函数。当agent加载以后,会从这里执行。Instrumentation 可以帮我们获取到所有加载到内存的类。然后根据要求筛选出合适的类进行重新转化。(省略掉attach代码)
利用这种方式。我们就可以把编译好的字节码准备好,然后以文件流的形式读取到内存中,进行动态的替换类的实现。

适用场景

重转换可能会更改方法体、常量池和属性。重转换不得添加、移除、重命名字段或方法;不得更改方法签名、继承关系。在以后的版本中,可能会取消这些限制。在应用转换之前,类文件字节不会被检查、验证和安装。如果结果字节错误,此方法将抛出异常。

这里是jdk文档里说明的,你的类如果是加了字段,那就不行了。文档中说可能会取消这些限制,现在是可以新增或删除方法,必须是private static以及private final。替换的过程会STW。这个过程非常短暂,相比替换版本而言,这个已经是代价非常小了。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1.6万
获赞与收藏
380

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消