Windows编译OpenJDK踩坑(持续更新).
编译
下载源码
准备boot JDK
C:\Program Files (x86)\Tencent\微信web开发者工具\dll
安装vs2017
使用C++的桌面开发
通用Windows平台开发
语言包选择English
cygwin
安装必要软件包
<path to Cygwin setup>/setup-x86_64 -q -P autoconf -P make -P unzip -P zip |
configu & compile
配置
cd path/openjdk17 |
编译
make LOG=info |
生成compile-database
make compile-commands |
使用wsl编译
安装必要软件包
下载好jdk源码后,解压到d:\openjdk\jdk11u
打开wsl shell,进入jdk源码目录
cd /mnt/d/openjdk/jdk11u |
配置
bash configure --with-debug-level=slowdebug --with-jvm-variants=server --disable-zip-debug-info --disable-warnings-as-errors --with-boot-jdk=/mnt/d/Aproject/openjdk/ |
编译
make |
生成 compile database
make compile-commands |
编译特定的模块
make CONF=config java.base-lib |
Clion Debug
Run/Debug Configurations > new Custom Build Application
name: jdk11-spring-boot-debug
Executeble:build\jdk\bin\java.exe
Program arguments:
-Xdebug -XX:+UseSerialGC -Xrunjdwp:server=y,transport=dt_socket,address=8099,suspend=n -Xlog:gc -Xms1000M -Xmn1000M -XX:-DoEscapeAnalysis -XX:+UseTLAB -XX:-ResizeTLAB -jar "D:\AProject\edian\backend\etc\api\certification-service\target\cs1.jar" -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintCompilation -XX:+PrintInlining -XX:CompileCommand=quiet |
Environment variables:
_JAVA_LAUNCHER_DEBUG =1 |
ref code:
src/java.base/share/native/launcher/main.c:146
#ifdef _WIN32
{
int i = 0;
if (getenv(JLDEBUG_ENV_ENTRY) != NULL) {
printf("Windows original main args:\n");
for (i = 0 ; i < __argc ; i++) {
printf("wwwd_args[%d] = %s\n", i, __argv[i]);
}
}
}
问题
assert(strcmp(value, system_value) == 0) failed: property value mustn’t differ from System.getProperty
出现这个问题,通常日志如下
# To suppress the following error report, specify this argument |
该问题是由于在bash configure
阶段,启用了调试,如--with-debug-level=*debug
(*指的是 slow
,fast
)
相关定义可在如下文件找到
make/hotspot/lib/JvmFlags.gmk:81
|
定位到相关源码则是
statSampler.cpp:180
void StatSampler::assert_system_property(const char* name, const char* value, TRAPS) { |
当比较到value
和system_value
不相等时,会抛出异常,
通过断点调试
此时的char* name
值为java.library.path
是由于环境变量PATH
中包含了带有中文的路径,导致system_value
转换为utf8时,中文字符转换为乱码,导致strcmp
不相等,从而抛出异常。
解决办法:把PATH
中的中文路径去掉,或者bash configure
阶段不要启用调试
补充1
如果是Windows平台 此时value
中存储的是GBK
编码后的path
值,value_oop存储的是UTF-16(LE)
编码后的path
值,经过
char* system_value = java_lang_String::as_utf8_string(value_oop);
后,system_value
存储的是utf8编码后的path
值,这个时候strcmp
比较字符串的结果是不相等的(因为有中文)
补充2
假如path
含有中文
字符 eg:c:\Hello\Abc-ZH-中文-Abc;
则有如下
字符 | GBK | UTF16 | UTF8 |
---|---|---|---|
中 | D6D0 | 4E2D | E4B8AD |
文 | CEC4 | 6587 | E69687 |
value
内存中的值(GBK编码)
6d 33 32 3b 43 3a 5c 57 49 4e 44 4f 57 53 3b 63 │ m32;C:\WINDOWS;c │ |
value_oop
在内存中的值(因为使用UTF16LE编码,所以字节序和大端模式相反)
57 00 53 00 3b 00 63 00 3a 00 5c 00 48 00 65 00 │ W·S·;·c·:·\·H·e· │ |
system_value
在内存中的值(UTF8编码)
6d 33 32 3b 43 3a 5c 57 49 4e 44 4f 57 53 3b 63 │ m32;C:\WINDOWS;c │ |
补充3
utf8
最小代码单元是一个字节
utf16
的最小代码单元是2个字节
complication-database.json 导入clion无法正确编译
使用make compile-commands
生成 compilation-database.json
将其导入到clion中,出现编译错误,原因是因为json中的编译命令路径问题,需要把\\\\
和 \\
替换为/
,然后重新导入即可。
arguments.cpp 969 解析+-参数选项
1162 解析JVM -XX参数
ref
jvm char*在内存中的存储方式为小端模式
- jstring 转char*
jstring value_oop;
java_lang_String::as_utf8_string(value_oop)
Can not determine compiler
Cannot determine compiler type by executable file: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\Hostx86\x64\ml64.exe' |
Clion plugins
cidr-base-plugin.jar
定义了各种编译器匹配实现,以及编译器调用逻辑
OCCompilerResolver
编译器解析工具
OCBuiltInCompilerResolver
默认实现类
主要匹配以下编译器
|
clion-compdb.jar
主要用于解析compile-commands.json
结构如下
[ |
当通过Clion
打开compile-commands.json
后,会进行Sync
操作,触发CompDBProjectResolver#resolveProjectInfo
通过遍历compile-commands.json
中的command
值,校验command
是否符合 cidr-base-plugin.jar
中定义的编译器。
如果command
中的命令不符合上述的编译器,那么会出现 Cannot determine compiler type by executable file: '/path/xxx'
这个错误,导致导入失败
private final void reportUnresolvedCompilers(ExternalSystemTaskId resolveTaskId, Set<? extends File> set, ExternalSystemTaskNotificationListener listener, String parentEventId) { |
解决方法
找到compile_commands.json
把所有含ml64.exe
相关的commands
删掉(注意删掉的是一个整体)
样例
[{ "directory": "d:/aproject/openjdk/jdk17/make", "file": "d:/aproject/openjdk/jdk17/src/jdk.incubator.vector/windows/native/libsvml/svml_d_acos_windows_x86.S", "command": "c:/progra~2/micros~2/2017/commun~1/vc/tools/msvc/1416~1.270/bin/hostx86/x64/ml64.exe -nologo -c -Fod:/aproject/openjdk/jdk17/build/windows-x86_64-server-slowdebug/support/native/jdk.incubator.vector/libsvml/svml_d_acos_windows_x86.obj d:/aproject/openjdk/jdk17/src/jdk.incubator.vector/windows/native/libsvml/svml_d_acos_windows_x86.S" }] |
再重新导入一下即可
Menu > Tools > Compilation Database > Reload Compilation Database Project
reference
Tips & Tricks: Develop OpenJDK in CLion with Pleasure
JBPM 异常分析.
JBPM 4.0
使用hibernate 3.6.0
作为数据持久框架,该版本依赖的javassist版本为3.12.0.GA
Hibernate中的每个Entity
其实都是代理过的类,由javassit
生成一个代理类
去继承Entity
类。
举个例子
public class Phone { |
你会发现
执行UserImplProxy.class.getDeclaredMethods()
后
你会发现返回结果“多出”一个synthetic bridge
方法getPhone()Lcom/project/pangu/cache/Phone; 0x1041 [public synthetic bridge]
(Java几种生成synthetic方法的情况,)
javassit
在代理目标类时,会把目标类中定义的所有方法都查询出来,形成Map<String,Method>
javassist 3.12.0.GA
private static void getMethods(HashMap hash, Class clazz) { |
Map的key
最终格式为:methodName:paramsTypes+returnType
javassit 3.16.0.GA
private static void getMethods(HashMap hash, Class clazz, Set visitedClasses) { |
Map的key
最终格式为:methodName:paramsTypes
当使用javaassist 3.12.0.GA
时,由于遍历目标类的方法时,Map使用的key为methodName:paramsTypes+returnType
,可以保证每个方法都能被代理到
由于项目中实际运行时使用的javassist
版本是3.16.0.GA
,(某个小伙伴引入的第三方库中使用javassist-3.16.0.GA
,覆盖了jbpm所依赖的javassist-3.12.0.GA
)
当遍历目标类的方法时,Map使用的key为methodName:paramsTypes
,当出现同名
,同形参
的方法时,这个时候能被代理到的方法和Class#getDeclaredMethods()
返回的顺序有关,该方法注释如下
Returns an array containing Method objects reflecting all the declared methods of the class or interface represented by this Class object, including public, protected, default (package) access, and private methods, but excluding inherited methods.
If this Class object represents a type that has multiple declared methods with the same name and parameter types, but different return types, then the returned array has a Method object for each such method.
If this Class object represents a type that has a class initialization method, then the returned array does not have a corresponding Method object.
If this Class object represents a class or interface with no declared methods, then the returned array has length 0.
If this Class object represents an array type, a primitive type, or void, then the returned array has length 0.
The elements in the returned array are not sorted and are not in any particular order (重点,返回数组中的元素没有排序,也没有特定顺序)
所以当执行下面代码时,有一定几率执行的方法不是代理过方法
UserImplProxy proxy = JavassistProxy(new UserImplProxy()); |
所以导致jbmp执行相关操作时,查询对象实体时,有一定几率导致返回为空(没有被代理,那么就不会触发查询)
lol-lcu-api
LCU-API
获取token
CMD以管理员权限运行,输入如下命令
wmic process where caption='LeagueClientUx.exe' get commandline |
得到如下结果
g:/英雄联盟/LeagueClient/LeagueClientUx.exe "--riotclient-auth-token=63-Wr1ACdIS6EfVkuy9gig" "--riotclient-app-port=58789" "--riotclient-tencent" "--no-rads" "--disable-self-update" "--region=TENCENT" "--locale=zh_CN" "--t.lcdshost=hn1-cloud-feapp.lol.qq.com" "--t.chathost=hn1-cloud-ejabberd.lol.qq.com" "--t.lq=https://hn1-cloud-login.lol.qq.com:8443" "--t.storeurl=https://hn1-cloud-sr.lol.qq.com:8443" "--t.rmsurl=wss://hn1-cloud-rms.lol.qq.com" "--rso-auth.url=https://prod-rso.lol.qq.com:3000" "--rso_platform_id=HN1" "--rso-auth.client=lol" "--t.location=loltencent.gz1.HN1" "--tglog-endpoint=https://tglogsz.datamore.qq.com/lolcli/report/" "--ccs=https://hn1-cloud-cc.lol.qq.com:8093" "--entitlements-url=https://hn1-cloud-entitlements.lol.qq.com:28088/api/token/v1" "--dradis-endpoint=http://some.url" "--remoting-auth-token=fBHICcvvUudE4Fij_kpQuA" "--app-port=58831" "--install-directory=g:\鑻遍泟鑱旂洘\LeagueClient" "--app-name=LeagueClient" "--ux-name=LeagueClientUx" "--ux-helper-name=LeagueClientUxHelper" "--log-dir=LeagueClient Logs" "--crash-reporting=" "--crash-environment=HN1" "--app-log-file-path=g:/英雄联盟/LeagueClient/../Game/Logs/LeagueClient Logs/2023-04-23T19-21-31_24144_LeagueClient.log" "--app-pid=24144" "--output-base-dir=g:/鑻遍泟鑱旂洘/LeagueClient/../Game" "--no-proxy-server" "--ignore-certificate-errors" |
参数说明
客户端api使用的https
协议,认证方式使用的是Basic
,用户名为riot
riot-client
riotclient-auth-token
token
riotclient-app-port
端口号
eg:
GET https://127.0.0.1:50886/swagger/v2/swagger.json
获取swagger文档说明
GET https://127.0.0.1:58789/swagger/v3/openapi.json
lcu-client
remoting-auth-token
token
app-port
端口号
reference
https://127.0.0.1:55205/lol-player-report-sender/v1/end-of-game-reports
{“gameId”:8293338498,”categories”:[“NEGATIVE_ATTITUDE”,”VERBAL_ABUSE”,”HATE_SPEECH”],”offenderSummonerId”:2947216121,”offenderPuuid”:”42924433-abf2-568c-a318-41f80cb50e57”}
https://pengu.lol/guide/lcu-request
https://hextechdocs.dev/getting-started-with-the-lcu-websocket/
https://riot-api-libraries.readthedocs.io/en/latest/lcu.html
https://www.nuget.org/packages/Camille.Lcu/
WinDbg符号配置.
配置环境变量
_NT_SYMBOL_PATH
:cache*C:\MySymbols;srv*https://msdl.microsoft.com/download/symbols
_NT_SYMBOL_PROXY
: ip:port
参考
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/bug-check-code-reference2
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/symbol-path
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/firewalls-and-proxy-servers
LOL ob教程.
设置
为了观战韩服职业选手排位历史记录
下载外服客户端
修改配置
到 C:\ProgramData\Riot Games\Metadata\league_of_legends.live
目录下
找到league_of_legends.live.product_settings.yaml
修改如下
auto_patching_enabled_by_player: false |
为了ob韩服不乱码,所以需要将上述的locale
后面的值改成ko_KR
- 修改观战进程语言
找到 LOL 安装目录 ,这里以我的为例,G:\Riot Games\League of Legends\Config
打开 LeagueClientSettings.yaml
文件,
修改如下
install: |
wireshark tls抓包.
二进制 && 位操作.
概论
计算中的任何数据都是由二进制表示,因为IC(Integrated Circuit)集成电路的引脚只有直流电压0V
或5V
两个状态,也就是一个IC引脚只能表示两个状态,和二进制 0
1
契合
数
二进制数0000 0101
转成10进制数结果为5 = 1*2^2 + 0*2^1 +1*2^0 = 4 + 0 + 1 = 5
即数值和位权
相乘后相加
正数和负数的表示
通常将数的二进制最高位作为符号位,1
表示负数,0
表示正数
10进制数1
的二进制数为:0000 0001
, 负数为 :~1 + 1 = -2 + 1 =-1
数v
取反:
正数:-(v+1)
负数 |v| -1
正数取反结果为负数,负数取反结果为整数
任何数取反加一的结果都为该数的相反数
正加负减(-(v+1)
)
以下数取反后的值 |
位移
只有右移时才能区分出逻辑位移
和算术位移
java中 >>
为算术右移,>>>
为逻辑位移
int x = -4; |
逻辑位移
补零就行了
算术位移
将二进制数作为带符号的数值进行运算时,移位后需要在最高位补充符号位(0或者1)
浮点数
符号、尾数、基数、指数
双精度(64bit)
符号部分(1bit) + 指数部分(11bit) + 尾数部分(52bit)
单精度(32bit)
符号部分(1bit) + 指数部分(8bit) + 尾数部分(23bit)
redis-源码学习总结.
sds (Simple dynamic string)
sdsHeader
sdsHdr{ |
List (双链表实现)
rio (面向stream的IO抽象层)
实现了sds
,file
,socket
,fd
的相关读写
其中针对aof(Append only file)
文件,定义了序列化协议 *<argv_num>\r\n$<count>\r\n<payload>\r\n
开启redis aof,需要在
redis.conf
中配置appendonly yes
例子:假如需要往aof
中写入字符串Hello
,实际写入的是$5\r\nHello
例子:redis-cli
执行set test abc
那么aof文件将会追加下面这段内容
*3 |
翻译成人话就是:三个字符串,分别为set test abc
dictht (HashTable)
其他
//设置状态flags |= STATE_OEPN
//取消状态flags &= ~STATE_OPEN
void updateFlag(int*flags,int flag,int enable){ |
spring-transaction-auto.
自动配置
@EnableTransactionManagement
-> @Import(TransactionManagementConfigurationSelector.class)
-> ProxyTransactionManagementConfiguration
ProxyTransactionManagementConfiguration
@Bean
-> BeanFactoryTransactionAttributeSourceAdvisor
->setTranactionAttributeSource (TransactionAttributeSource())
->setAdvice(TransactionInterceptor()->ref->TransactionManager)
7vPUtZJ6pMgebJvzi4C,eWDpdRrVLwQk56uCCIE