1.Jvm-Sandbox原理分析-Sandbox的源码启动-01
2.springboot如何进行混淆加密(proguard+xjar)
3.XJar(防源码泄漏)使用指南
4.万字长文入门Vert.x
Jvm-Sandbox原理分析-Sandbox的启动-01
Jvm-Sandbox的启动(一):sandbox.sh脚本分析
Sandbox的启动是通过其内置的shell脚本 sandbox.sh 开始执行的,一切的解析开始皆可从该脚本中探寻出结果。脚本有一定的源码代码量,大概有+行,解析这里将该脚本分为如下几个部分进行讲解:
1、源码变量定义过程这个过程首先预定义了接下来即将使用的解析vb源码 加密一些变量。代码如下:
# 定义sandbox的源码home目录,并为其赋值 typeset SANDBOX_HOME_DIR [[ -z ${ SANDBOX_HOME_DIR} ]] && SANDBOX_HOME_DIR=${ PWD}/..# 定义 SANDBOX_USER,解析并为其赋值 typeset SANDBOX_USER=${ USER} [[ -z ${ SANDBOX_USER} ]] && SANDBOX_USER=$(whoami)# 定义 SANDBOX_SERVER_NETWORK typeset SANDBOX_SERVER_NETWORK# 定义lib目录,源码这个目录下主要存放jar包 typeset SANDBOX_LIB_DIR=${ SANDBOX_HOME_DIR}/lib# 定义 SANDBOX_TOKEN_FILE typeset SANDBOX_TOKEN_FILE="${ HOME}/.sandbox.token"# 定义JVM参数 SANDBOX_JVM_OPS typeset SANDBOX_JVM_OPS="-XmsM -XmxM -Xnoclassgc -ea"# 定义目标JVM的解析进程号,后面的源码agent主要attach到该JVM进程上 typeset TARGET_JVM_PID# 定义目标机器IP以及默认机器IP typeset TARGET_SERVER_IP typeset DEFAULT_TARGET_SERVER_IP="0.0.0.0"# 定义目标进程端口 typeset TARGET_SERVER_PORT# 定义名称空间 typeset TARGET_NAMESPACE typeset DEFAULT_NAMESPACE="default"注释和变量命名已经描绘的非常清楚了,在看后面代码遇到忘记了的解析变量可以到这里来回顾下。
这里为其中一些变量补充说明:
SANDBOX_HOME_DIR:shell脚本中,源码-z表示检测紧跟的解析字符串长度是否为0,如果为0返回true。源码这里使用短路与,如果 ${ SANDBOX_HOME_DIR} 为0,则使用 ${ PWD}/.. 的目录作为sandbox的home目录。这种方式表示优先使用环境变量 SANDBOX_HOME_DIR,glibc源码阅读如果未定义环境变量SANDBOX_HOME_DIR,则使用当前目录。
SANDBOX_TOKEN_FILE:这个文件主要存放了sandbox attach记录,包括attach进程的host:port。
TARGET_SERVER_IP:一般情况下,我们都是将整个工程打包后上传至目标机器,然后在目标机器上执行该shell脚本,因此默认机器IP一般为localhost即可。
2、执行入口执行入口就比较简单了,就一行代码,其中${ @}会保存我们传递给该shell脚本的所有参数:
main "${ @}"比方说,我们以如下命令启动脚本,则${ @} 就包含了-p 这个参数
./sandbox.sh -p 、main函数main函数是该脚本的重要方法,也是脚本的执行入口,它主要完成了以下几件事:
其代码如下所示:
function main() { # 遍历脚本参数 while getopts "hp:vFfRu:a:A:d:m:I:P:ClSn:X" ARG; do case ${ ARG} in h) # 帮助手册函数,大家可以自行翻阅源码查看 usage exit ;; # 赋值PID p) TARGET_JVM_PID=${ OPTARG} ;; v) OP_VERSION=1 ;; l) OP_MODULE_LIST=1 ;; R) OP_MODULE_RESET=1 ;; F) OP_MODULE_FORCE_FLUSH=1 ;; f) OP_MODULE_FLUSH=1 ;; u) OP_MODULE_UNLOAD=1 ARG_MODULE_UNLOAD=${ OPTARG} ;; a) OP_MODULE_ACTIVE=1 ARG_MODULE_ACTIVE=${ OPTARG} ;; A) OP_MODULE_FROZEN=1 ARG_MODULE_FROZEN=${ OPTARG} ;; d) OP_DEBUG=1 ARG_DEBUG=${ OPTARG} ;; m) OP_MODULE_DETAIL=1 ARG_MODULE_DETAIL=${ OPTARG} ;; # 赋值IP I) TARGET_SERVER_IP=${ OPTARG} ;; # 赋值PORT P) TARGET_SERVER_PORT=${ OPTARG} ;; C) OP_CONNECT_ONLY=1 ;; S) OP_SHUTDOWN=1 ;; n) OP_NAMESPACE=1 ARG_NAMESPACE=${ OPTARG} ;; X) set -x ;; ?Android 换装源码) usage exit_on_err 1 ;; esac done # 重置环境 reset_for_env # 校验权限 check_permission# 根据不同的参数,进行相应处理 # 如果没有指定IP,则使用默认值 [ -z "${ TARGET_SERVER_IP}" ] && TARGET_SERVER_IP="${ DEFAULT_TARGET_SERVER_IP}"# 如果没有指定port,使用默认值 [ -z "${ TARGET_SERVER_PORT}" ] && TARGET_SERVER_PORT=0# reset NAMESPACE [[ ${ OP_NAMESPACE} ]] && TARGET_NAMESPACE=${ ARG_NAMESPACE} [[ -z ${ TARGET_NAMESPACE} ]] && TARGET_NAMESPACE=${ DEFAULT_NAMESPACE}if [[ ${ OP_CONNECT_ONLY} ]]; then [[ 0 -eq ${ TARGET_SERVER_PORT} ]] && exit_on_err 1 "server appoint PORT (-P) was missing" SANDBOX_SERVER_NETWORK="${ TARGET_SERVER_IP};${ TARGET_SERVER_PORT}" else # -p was missing [[ -z ${ TARGET_JVM_PID} ]] && exit_on_err 1 "PID (-p) was missing." # attach jvm的核心方法 attach_jvm fi# -v show version [[ -n ${ OP_VERSION} ]] && sandbox_curl_with_exit "sandbox-info/version"# -l list loaded modules [[ -n ${ OP_MODULE_LIST} ]] && sandbox_curl_with_exit "sandbox-module-mgr/list"# -F force flush module [[ -n ${ OP_MODULE_FORCE_FLUSH} ]] && sandbox_curl_with_exit "sandbox-module-mgr/flush" "&force=true"# -f flush module [[ -n ${ OP_MODULE_FLUSH} ]] && sandbox_curl_with_exit "sandbox-module-mgr/flush" "&force=false"# -R reset sandbox [[ -n ${ OP_MODULE_RESET} ]] && sandbox_curl_with_exit "sandbox-module-mgr/reset"# -u unload module [[ -n ${ OP_MODULE_UNLOAD} ]] && sandbox_curl_with_exit "sandbox-module-mgr/unload" "&action=unload&ids=${ ARG_MODULE_UNLOAD}"# -a active module [[ -n ${ OP_MODULE_ACTIVE} ]] && sandbox_curl_with_exit "sandbox-module-mgr/active" "&ids=${ ARG_MODULE_ACTIVE}"# -A frozen module [[ -n ${ OP_MODULE_FROZEN} ]] && sandbox_curl_with_exit "sandbox-module-mgr/frozen" "&ids=${ ARG_MODULE_FROZEN}"# -m module detail [[ -n ${ OP_MODULE_DETAIL} ]] && sandbox_curl_with_exit "sandbox-module-mgr/detail" "&id=${ ARG_MODULE_DETAIL}"# -S shutdown [[ -n ${ OP_SHUTDOWN} ]] && sandbox_curl_with_exit "sandbox-control/shutdown"# -d debug if [[ -n ${ OP_DEBUG} ]]; then sandbox_debug_curl "module//post/springboot如何进行混淆加密(proguard+xjar)
项目组核心代码模块部署在用户服务器上,面临安全风险,常规部署方式可能导致数据泄露与代码泄露。为解决这一问题,选择采用代码混淆加密技术,确保数据与代码安全。
项目选择proguard作为混淆工具,主要因为其能够有效处理Spring Boot单体应用,通过修改Maven插件配置,结合Jasypt实现配置文件加密。
采用Xjar进行jar包加密,简化配置流程,避免源码泄露与反编译。具体步骤包括下载Xjar demo,将生成的jar包和自定义密码脚本放置在同级目录,使用Maven命令完成混淆代码编译,ivy 获取源码并生成加密后的jar包。设置启动脚本添加加密密钥参数,实现安全启动。
混淆前后的对比结果显示,加密处理显著提升了代码和配置文件的安全性,有效防止数据泄露与代码曝光。
总结,通过结合proguard与Xjar,项目实现了高效、安全的代码混淆加密,确保了核心代码模块在部署过程中的安全性。
XJar(防源码泄漏)使用指南
Spring Boot JAR安全加密运行工具,提供了一种对JAR包内资源加密及动态解密运行的方案,旨在避免源码泄露及反编译。该工具支持原生JAR,并基于JDK 1.7或更高版本与Go环境。
功能特性与环境依赖包括:JDK 1.7或以上版本,以及Go环境。activiti 源码解析为了集成该工具,需要在Maven构建过程中添加依赖,并集成xjar-maven-plugin(GitHub链接:github.com/core-lib/xja...)。
使用步骤如下:
1. 添加依赖于Maven构建文件中。
2. 集成插件:Maven构建自动生成加密后的JAR文件及Go启动器源码。
3. 打包时指定加密密码。完成后,生成的文件包含加密后的JAR包。
4. 下载并安装Go环境(下载地址:golang.google.cn/dl/)。
5. 生成用于启动运行的Go环境下的可执行文件。
6. 使用生成的文件启动运行程序。
万字长文入门Vert.x
关于BIO和NIO,老生常谈的话题,主要分为BIO、NIO和AIO。在实际使用中,BIO和NIO更广泛,NIO相较于BIO,具有更好的并发能力,更节省资源。AIO作为异步非阻塞IO,在当前技术环境下应用还不广泛。
在Java中,BIO、NIO和AIO都支持,NIO在Java 1.7引入为NIO2。实际使用中,netty基于NIO实现,但有自己的模型,本质上都是IO多路复用。需澄清BIO是同步阻塞IO,NIO是同步非阻塞IO,AIO是异步非阻塞IO。
select、poll、epoll和NIO关系主要关注的是区别,它们都是NIO的实现手段。NIO相较于BIO,更具备并发能力,能处理更多请求,但开发成本更高。底层框架或性能敏感场景会考虑使用NIO。
Eclipse Vert.x是一个事件驱动的编程框架,通过抽象提供高性能,让开发者以较低成本享受到NIO优势。Vert.x底层使用netty进行通讯,但对netty细节进行了封装,减少了使用门槛。用户可以基于Vert.x的扩展组件,而netty提供了底层逻辑支持。
使用Vert.x构建简单的HttpServer,只需几行代码,但完整的HttpServer还需处理HTTP协议层面。Vert.x封装了路由功能,通过Router实现。发布Vert.x应用以jar包形式,依赖轻,发布包体积小,适用于服务逻辑复杂度不高且关注性能的场景。
Vert.x提供性能测试,显示相比于Spring,它在多方面表现更优。Vert.x的核心在于黄金法则:永远不要阻塞EventLoop。阻塞会导致无法响应其他事件,引发性能问题。官方文档详细说明了哪些情况可能构成阻塞。
Vert.x提供了executeBlocking方法来处理阻塞代码,通过固定大小线程池避免阻塞事件循环。但推荐避免使用此方法,因为它涉及线程上下文切换,带来性能损耗。Vert.x设计为将连续代码分割,始终在同一个线程上执行,模拟协程运行,以解决阻塞问题。
Vert.x提供了多种原生组件,如vertx-redis-client、vertx-kafka-client等,直接从TCP层面实现协议,实现真正的异步。Context在Vert.x中起串联执行路径、分离阻塞和非阻塞操作的作用,Context原理可通过相关文章了解。
在实际使用中,Vert.x与第三方框架集成时,合理利用Context避免不必要的线程上下文切换。以Caffeine和Failsafe为例,构造实例时通过Context模拟Executor,避免额外线程池的使用。
使用Vert.x native-transport时,引入netty native支持以获取更高性能。需确保netty版本与Vert.x一致,进行额外配置。
实际应用中,通过具体项目Demo展示Vert.x功能,欢迎交流。个人水平有限,可能有疏漏,欢迎提问讨论。推荐关注公众号,获取更多资源。