游戏服务器之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显示,或者修改游戏的逻辑,这个时候,如果不使用热更新,就需要重新 ...
随机推荐
- Nginx 反向代理获取设备真实的IP地址
package com.das.common.util; import org.apache.commons.lang3.StringUtils; import org.springframework ...
- Windows10 + IntelliJ IDEA 2017.3.2 + wamp2e + xdebug 调试 配置
一.环境 系统: windows10 WampServer: wampserver2.2e-php5.3.13-httpd2.2.22-mysql5.5.24-32b.exe IDE: Intel ...
- java应用监控工具
http://hao.jobbole.com/category/java/java-monitoring/
- linux查找并替换命令
find ./ -maxdepth 3 -type f -name "*Makefile" |xargs sed -i "s/CXX = g++/CXX = ccac ...
- python @staticmethod和@classmethod的作用
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法. 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用. 这有利于组织代码,把某些应 ...
- Centos6.8 安装spark-2.3.1 以及 scala-2.12.2
一.Spark概述 Spark 是一个用来实现快速而通用的集群计算的平台. 在速度方面,Spark 扩展了广泛使用的 MapReduce 计算模型,而且高效地支持更多计算模式,包括交互式查询和流 ...
- Centos 7内核3升级到4
步骤 1:检查已安装的内核版本 让我们安装了一个发行版,它包含了一个特定版本的内核.为了展示当前系统中已安装的版本,我们可以: # uname -sr 下面的图片展示了在一台 CentOS 7 服务器 ...
- 最大团&优化
貌似咕了三个半月了(gym101915里一道),今天又遇到一道(cf1105E),就学了学惹. 最大团定义:图上取尽可能多的点,这些点构成一个完全图. 最大独立集:图上取尽可能多的点,任意两点间不连接 ...
- RabbitMQ之路由键转发消息
RabbitMQ学习 参考:https://www.jianshu.com/p/6b62a0ed2491 消息队列:目前流行的有 Kafka.RabbitMQ.ActiveMQ等 功能:为了解决消息的 ...
- Apache hardoop 的基础知识学习总结
hardoop的主要构成: (1)HDFS 分布式文件系统,解决海量数据存储 (2) YARN 解决资源任务调度(包括作业调度和集群资源调度) (3)MapReduce 解决海量数据计算 集群搭建的步 ...