0

请教下 Java 热替换代码的技术

 1 year ago
source link: https://www.v2ex.com/t/882334
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Java

请教下 Java 热替换代码的技术

  8629 · 8 小时 37 分钟前 · 2530 次点击
场景:把接收处理数据的类 源码放在 web 后台页面中在线编辑,编辑完这个类直接提交到 redis 中。然后线上服务就替换了这部分代码,不需要打包发布实现了更新服务。
请问这是什么技术,什么关键字可以查询,有没有现成的 demo 可以学习下。感谢!
49 条回复    2022-09-23 19:02:22 +08:00
nothingistrue

nothingistrue      8 小时 35 分钟前   ❤️ 1

你这要能实现,得推翻 Java 的编译原理。
sunjiayao

sunjiayao      8 小时 33 分钟前   ❤️ 1

groovy 你值得拥有
XiLingHost

XiLingHost      8 小时 33 分钟前

把新的代码自动构建成一个镜像,然后调整服务路由做灰度发布就行了,调用方可以无感
wxw752

wxw752      8 小时 32 分钟前   ❤️ 2

就因为这个问题,我们公司到现在还有一块业务用的 PHP
LeegoYih

LeegoYih      8 小时 31 分钟前

GitHub 搜 Java HotSwap 还是有挺多 demo 的,不过能替换的程度有限
twinsdestiny

twinsdestiny      8 小时 30 分钟前

groovy 可以
justicelove

justicelove      8 小时 30 分钟前

groovy
wangxiaoaer

wangxiaoaer      8 小时 29 分钟前   ❤️ 1

@nothingistrue ??? 怎么叫推翻呢。

javax.tools 本身就提供了编译 java 文件的途径,再加上 classloader 替换,技术上应该是可行的。
superchijinpeng

superchijinpeng      8 小时 28 分钟前

@nothingistrue 无非是 Class Load 和 Unload 一下
chendy

chendy      8 小时 28 分钟前

编译 api+反射,不是替换是新增……
每次生成一个新类名,编译出 class 文件,再把调用的地方的类名替换上去,完事
justicelove

justicelove      8 小时 26 分钟前

可以搜一下 java 脚本 一般都会选择 Groovy, 也可以使用 spi, 在服务器上替换 jar 包
aguesuka

aguesuka      8 小时 25 分钟前

鉴于有在线编辑的需求, 建议直接用 groovy 脚本. 完全兼容 java 对象, 无需编译, 也就不需要热替换.
Dxxxxs

Dxxxxs      8 小时 23 分钟前

可以看一下 jvm 提供的 Instrumentation 类。JRebel 、springboot dev tools 、HotSwapAgent 都提供了类似的实现
pannanxu

pannanxu      8 小时 19 分钟前

Jooooooooo

Jooooooooo      8 小时 12 分钟前

自定义 classloader 就行. 加载这个 jar. 然后跑方法的时候用反射拿到你热加载的那个.

我们刚好有这么搞的, 引入算法包天天变, 就用的这个方法不用发版能用上最新的

不过有几个注意点你得考虑下:

1. 有 load 记得要 unload
2. 如果是集群, 要保证所有集群都加载完了再去用, 所以需要维护机器当前加载某个 jar 的状态, 最好有个后台去查看和使用, 全部机器都加载完了才能真正使用
VYSE

VYSE      7 小时 55 分钟前

关键字: JAVA 反序列化漏洞
这么搞后台得管控好
m2276699

m2276699      7 小时 49 分钟前

cn.hutool.core.compiler/sofa ark
cpstar

cpstar      7 小时 46 分钟前

java 语言层面支持。然后就是你的应用底层需要支持。我目前正在用的一个平台微应用化就支持动态加载,关闭某个应用或者打开,更新了 jar 之后动态重加载。
但是我目前用的平台支持 beanshell 、groovy 、javascript 的在线编辑和编译,java 代码的编辑和编译再加载不知道有没有库。javascript 方面使用的是 apache rhino 库,翻译 js 并运行。
ic2y

ic2y      7 小时 42 分钟前

为什么不用规则引擎,专门处理这种事。例如 Aviator
xiangxiangxiang

xiangxiangxiang      7 小时 41 分钟前

groovy 脚本+1 之前有场景就是 m 端维护 /发布代码块,然后在 c 端动态加载生效
Vegetable

Vegetable      7 小时 39 分钟前

标准的 RPC API 、自动构建、容器化
coala

coala      7 小时 4 分钟前

类似 JSP 呗.
q1angch0u

q1angch0u      7 小时 1 分钟前 via iPhone

grpovy 啊…
paullee

paullee      6 小时 57 分钟前 via iPhone

花这些功夫,用 k8s 部署,滚动更新,不是更舒服?
humpy

humpy      6 小时 38 分钟前

可以做,jdk 提供了 JavaCompiler ,可以在运行时编译代码,将编译后的代码存在内存里,再实现一个 ClassLoader ,就能加载刚编译的类了。

可以参考一下这篇文章,好像是微博的老师写的:
https://zhenbianshu.github.io/2019/12/play_with_java_dynamic_compile.html
misaka19000

misaka19000      6 小时 22 分钟前 via Android

可以用 ASM 动态替换字节码来做,或者用 ByteBuddy 使用更高级一些的 API
molika

molika      5 小时 57 分钟前

jvm 上用 Clojure 天生支持
codehz

codehz      5 小时 54 分钟前

还记得之前的 jndi 漏洞吗(
听着就是在造 RCE(
xuanbg

xuanbg      5 小时 47 分钟前

能搞!办法还不少,但没一个是安全的。想想也知道,这就相当于代码不经过审查和测试就直接上线,我写几个漏洞也是没什么问题的吧?谁还不写几个 bug 呢。。。
nothingistrue

nothingistrue      5 小时 38 分钟前

@wangxiaoaer #8
@superchijinpeng #10
仔细看:“编辑完这个类直接提交到 redis 中”,“不需要打包”。这是想源码一步到底的,Classloader 可 load 不了。
superchijinpeng

superchijinpeng      5 小时 14 分钟前

@nothingistrue URLClassLoader ,参考 Spark 或者 Flink 动态注册或移除 UDF
zhang77555

zhang77555      5 小时 8 分钟前

JavaCompiler 把代码编译成 class 然后 URLClassLoader 加载
建议定好接口和编码模板校验,免得这部分功能被滥用
selca

selca      5 小时 5 分钟前

@codehz #33 私有的东西,目的就是造一个门去调,如果操作者能控制好鉴权,还是没问题的
dddyyyttt

dddyyyttt      4 小时 37 分钟前

为什么没人提 arthas ?
wangxiaoaer

wangxiaoaer      4 小时 37 分钟前

@nothingistrue 我理解他的意思是 java 代码存到 redis ,但是肯定不能和直接用,后台可以从 redis 读这些代码编译,替换。

如果想直接从 redis 加载 java 文件就替换运行,那肯定是不行的。
3032

3032      4 小时 33 分钟前

阿里的阿尔萨斯了解下
vvtf

vvtf      4 小时 25 分钟前

1. 通过 Agent 拿到 Instrumentation
2. 通过 Instrumentation#redefineClasses 替换类即可.
leegradyllljjjj

leegradyllljjjj      4 小时 17 分钟前

v 我 50 ,我帮你守着服务器,你一提交代码我就帮你编译发布
zgzhang

zgzhang      4 小时 9 分钟前

这样的东西很成熟呀,我做的类似的项目,核心原理就是 Java 的动态编译+spring bean 的替换,如果有需要可以联系我
BiChengfei

BiChengfei      3 小时 34 分钟前

magic-api
warcraft1236

warcraft1236      2 小时 49 分钟前

这个跟热更新不是一个原理吗
thisisgpy

thisisgpy      1 小时 47 分钟前

先把 class restransform 回来,记录一下当前在用 classloader 的 hashcode ,新的代码编译后找到刚才的 classloader rebase 进去
Znemo

Znemo      1 小时 21 分钟前

classloader 就能做到,但是这要围绕这种编程模型来架构,一般的业务代码可以这样热替换,核心代码例如 class 的加载、事件调度等就很难做到了,另外方法区的垃圾回收要关注,被替换掉的 class 要有有效的回收机制。除非精心设计,否则需要注意的问题还是蛮多的。
hetal

hetal      30 分钟前

换成 php 是不是更简单~

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK