游戏服务器之Java热更新
对于运行良好的游戏来说,停服一分就会损失很多收益。因为有些小bug就停服就划不来了。在使用Java开游戏服务器时,JVM给我们提供了一些接口,可以简单做一些热更新。修复一些小Bug而不用重启服务。
JVM可以给运行中的服务器绑定一个代理,在这个代理中可以拿到Instrumentation 这个类的实例,它可以让用户手动修改jvm中的class类,对它进行热更新,但是有一点,用于热更新的新类和老的类方法签名必须一样,即不能修改方法的名字,参数类型,还有修改声明的字段。只能修改方法体里面的代码。一般的小bug都是方法体内的逻辑漏洞,不会做很多大的修改,所以这种方式还是能满足我们的需要求的。
现在我们分三个项目:
1,GameServer 即我们正常的游戏服务器。
2,LoadAgent 这个是热更新的代理项目,热更新的操作就在这里面执行。
3,GameServerHotBoot 这个项目是用来把LoadAget代理和GameServer进行绑定的。
JDK代理的两种方式:
1.premain方式是Java SE5开始就提供的代理方式,但其必须在命令行指定代理jar,并且代理类必须在main方法前启动,它要求开发者在应用启动前就必须确认代理的处理逻辑和参数内容等等
2.agentmain方式是JavaSE6开始提供,它可以在应用程序的VM启动后再动态添加代理的方式
应用场景:
premain这种方式必须在jar包启动的时候进行指定,它是运行在项目的main方法之前的,即项目启动时:
java – javaagent:LoadAgent.jar -jar GameServer.Jar
但是正常的生产环境下,一般不会开启代理功能,但是在发生问题时,我们不希望停止应用就能够动态的去修改一些类的行为,以帮助排查问题,这在应用启动前是无法确定的。这时agentmain就可以做到了。所以我们采用agentmain这种方式。
1,LoadAgent实现
这个实现也比较简单,就像我们的程序入口有main方法一样,它需要一个agemtmain方法
public class GameServerAgent {
public static void agentmain(String args, Instrumentation inst) throws Exception {
System.out.println("agent 启动成功,开发重定义对象....");
Class<?>[] allClass = inst.getAllLoadedClasses();
for (Class<?> c : allClass) {
if (c.getName().endsWith("TestHot")) {
String pathname = "config\\TestHot.class";
File file = new File(pathname);
try {
byte[] bytes = fileToBytes(file);
System.out.println("文件大小:" + bytes.length);
ClassDefinition classDefinition = new ClassDefinition(c, bytes);
inst.redefineClasses(classDefinition);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("转换代码。。。");
}
}
System.out.println("热更新成功....");
}
public static byte[] fileToBytes(File file) throws IOException {
FileInputStream in = new FileInputStream(file);
byte[] bytes = new byte[in.available()];
in.read(bytes);
in.close();
return bytes;
}
}
对某个class的替换有两种方式
1,使用ClassFileTransformer
2,使用ClassDefinition
由于ClassDefinition比较方便,所以我们使用ClassDefinition对类进行更新。
项目源码地址:https://github.com/youxijishu/game-hot-update
热更新步骤:
1,打包LoadAgent
在使用LoadAgent的时候,需要在MANNIFEST.MF添加一些属性
Agent-Class: com.xinyue.hot.agent.GameServerAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
这个在可以在打包的pom.xml中配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath> </manifest>
<manifestEntries>
<Agent-Class>
com.xinyue.hot.agent.GameServerAgent
</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
然后使用mvn install命令即可,在target中找到生成的jar,LoadAgent-0.0.1-SNAPSHOT.jar,把它放到GameServer下的config目录下面,这里是测试,用的相对路径。
2,在GameServer中创建一个测试的类,叫TestHop.java,使用里面有一个输出方法,打印1,然后使用mvn install进行编译,在target/classes中找到这个类,把它也复制到GameServer的config路径下面。
3,把TestHop类中的输出修改为2,运行GameServer,这时会输出pid和2
4,把pid复制到GameServerHotUpdate的HotUpdateMain类中,当然,在实际应用中也可以通过args传进来。然后运行HotUpdateMain,等会儿就会输出结果


这时我们发现类的输出变化了,没有热更之前输出是的2,热更新之后,输出的是1.说明,热更新成功了。
项目源码地址:https://github.com/youxijishu/game-hot-update
QQ群交流:66728073,更多文章:http://www.coc88.com;公众号:

游戏服务器之Java热更新的更多相关文章
- spring boot热部署 -- 实现 后端java热更新 -- 详细操作 【idea 的 JRebel破解】
1.前言 上一随笔写了如何使得spring boot热更新前端 ,但后端java部分无法热更新. 对于Java热更新,以前常使用 springloaded ,但是缺点 和bug很多 无法实现真正意 ...
- (4/24) webpack3.x快速搭建本地服务和实现热更新
写在前面: (1)为了防止版本兼容问题,此处的webpack版本与之前的一致为:webpack@3.6.0.同时这里我们安装的webpack-dev-server版本是2.9.7版本. (2)之前已经 ...
- Java 热更新 Groovy 实践及踩坑指南
Groovy 是什么? Apache的Groovy是Java平台上设计的面向对象编程语言.这门动态语言拥有类似Python.Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用 ...
- C#热血传奇游戏服务端再次开源更新
2014年新春佳节即将到来,也算是送给大家的一份新年礼物.虽然这礼物貌似不给力啊哈哈.(没有用心啊 o(∩_∩)o 哈哈) 这次开源主要去掉上一次开源版本中大量指针代码,简化上手操作,并重构大部分代码 ...
- unity游戏热更新
链接:https://pan.baidu.com/s/1ggWP0OF 第 1 章 : 热更新技术学习介绍 课时1:101-热更新技术学习介绍 11:55 什么是热更新? 举例来说 游戏上线后,玩家下 ...
- spring cloud --- 使用 actuator 热更新【刷新】单机配置文件
1.前言 分布式微服务想要热更新配置文件,还需要 消息中间件 配合使用 ,一般使用 rabbitMQ 或 Kafka ,这里不解释 . 这篇随笔 只讲解 底层的 单机热更新配置文件 2.环境 spri ...
- lua转让C++书面DLL达到“热更新”
原创作品,请注明出处转载CSDN:http://blog.csdn.net/relar/article/details/38084689 开发游戏server往往有"热更新"的需求 ...
- [Android教程] Cordova开发App入门(二)使用热更新插件
前言 不知各位遇没遇到过,刚刚发布的应用,突然发现了一个隐藏极深的“碧油鸡(BUG)”,肿么办!肿么办!肿么办!如果被老板发现,一定会让程序员哥哥去“吃鸡”.但是想要修复这个“碧油鸡”,就必须要重新打 ...
- Unity热更新技术整理
一.热更新学习介绍 1.什么是热更新 举例来说: 游戏上线后,玩家下载第一个版本(70M左右或者更大),在运营的过程中,如果需要更换UI显示,或者修改游戏的逻辑,这个时候,如果不使用热更新,就需要重新 ...
随机推荐
- TextView 链接显示及跳转
当文字中出现URL.E-mail.电话号码等的时候,我们为TextView设置链接.总结起来,一共有4种方法来为TextView实现链接.我们一一举例介绍: 1. 在xml里添加android:aut ...
- 软件工程---gjb438b 质量规范体系
GJB438B 软件设计说明模板 https://mp.weixin.qq.com/s?__biz=MjM5Mzc2NjczMQ%3D%3D&idx=3&mid=2651866777& ...
- JavaScript异步并发请求问题
JavaScript异步并发请求问题 JS中如何处理多个ajax并发请求? jQuery的deferred对象详解 面试遇到的ajax请求串行和并行问题
- 智能聊天机器人——基于RASA搭建
前言: 最近了解了一下Rasa,阅读了一下官方文档,初步搭建了一个聊天机器人. 官方文档:https://rasa.com/docs/ 搭建的chatbot项目地址: https://github.c ...
- IntelliJ IDEA License Server 安装使用 Mac篇
一.下载 IntelliJ IDEA 是Java开发利器,用社区版不爽,干催就用旗舰版,这个是收费的,需要licence. IntelliJ IDEA下载地址:https://www.jetbrai ...
- Jquery实现轮播公告
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- sql知识点记录
order by就是排序. group by就是分组. WHERE语句在GROUP BY语句之前:SQL会在分组之前计算WHERE语句. HAVING语句在GROUP BY语句之后:SQL会在分 ...
- 编译wxWidgets
打开x64 Native Tools Command Prompt for VS 2017 cd wxWidgets-2.9.5\build\msw nmake -f makefile.vc TARG ...
- Golang etcd服务注册与发现
//sevice.go package discovery import ( "context" "errors" "sync" " ...
- [LeetCode] Flip Game II 翻转游戏之二
You are playing the following Flip Game with your friend: Given a string that contains only these tw ...