随记

......

Enable

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\NVIDIA Corporation\Global\NGXCore]
"ShowDlssIndicator"=dword:00000001

Disable

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\NVIDIA Corporation\Global\NGXCore]
"ShowDlssIndicator"=dword:00000000

编译

下载源码

AdoptOpenJDK/openjdk-jdk11u

jdk-updates

准备boot JDK

JDK release

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

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 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
# after -XX: or in .hotspotrc: SuppressErrorAt=\statSampler.cpp:204
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (d:\aproject\openjdk\jdk17\src\hotspot\share\runtime\statSampler.cpp:204), pid=4488, tid=21828
# assert(strcmp(value, system_value) == 0) failed: property value mustn't differ from System.getProperty
#
# JRE version: OpenJDK Runtime Environment (17.0) (slowdebug build 17-internal+0-adhoc.edian.jdk17)
# Java VM: OpenJDK 64-Bit Server VM (slowdebug 17-internal+0-adhoc.edian.jdk17, mixed mode, tiered, compressed oops, com
pressed class ptrs, g1 gc, windows-amd64)
# Core dump will be written. Default location: D:\AProject\openjdk\jdk17\build\windows-x86_64-server-slowdebug\jdk\bin\h
s_err_pid4488.mdmp

该问题是由于在bash configure阶段,启用了调试,如--with-debug-level=*debug (*指的是 slow,fast)
相关定义可在如下文件找到

make/hotspot/lib/JvmFlags.gmk:81


ifeq ($(DEBUG_LEVEL), release)
# For hotspot, release builds differ internally between "optimized" and "product"
# in that "optimize" does not define PRODUCT.
ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized)
JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT
endif
else ifeq ($(DEBUG_LEVEL), fastdebug)
JVM_CFLAGS_DEBUGLEVEL := -DASSERT
ifeq ($(call isTargetOs, windows aix), false)
# NOTE: Old build did not define CHECK_UNHANDLED_OOPS on Windows and AIX.
JVM_CFLAGS_DEBUGLEVEL += -DCHECK_UNHANDLED_OOPS
endif
else ifeq ($(DEBUG_LEVEL), slowdebug)
# _NMT_NOINLINE_ informs NMT that no inlining is done by the compiler
JVM_CFLAGS_DEBUGLEVEL := -DASSERT -D_NMT_NOINLINE_
endif

定位到相关源码则是

statSampler.cpp:180

void StatSampler::assert_system_property(const char* name, const char* value, TRAPS) {
#ifdef ASSERT
ResourceMark rm(THREAD);

// setup the arguments to getProperty
Handle key_str = java_lang_String::create_from_str(name, CHECK);

// return value
JavaValue result(T_OBJECT);

// public static String getProperty(String key, String def);
JavaCalls::call_static(&result,
vmClasses::System_klass(),
vmSymbols::getProperty_name(),
vmSymbols::string_string_signature(),
key_str,
CHECK);

oop value_oop = result.get_oop();
assert(value_oop != NULL, "property must have a value");

// convert Java String to utf8 string
char* system_value = java_lang_String::as_utf8_string(value_oop);
printf("\tA system value: %s -> \n%s\n\n",name,system_value);
assert(strcmp(value, system_value) == 0, "property value mustn't differ from System.getProperty");
#endif // ASSERT
}

当比较到valuesystem_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 │
3a 5c 48 65 6c 6c 6f 5c 41 62 63 2d 5a 48 2d d6 │ :\Hello\Abc-ZH-· │
d0 ce c4 2d 41 62 63 3b 43 3a 5c 47 6e 75 57 69 │ ···-Abc;C:\GnuWi │

value_oop 在内存中的值(因为使用UTF16LE编码,所以字节序和大端模式相反)

57 00 53 00   3b 00 63 00   3a 00 5c 00   48 00 65 00   │ W·S·;·c·:·\·H·e· │
6c 00 6c 00 6f 00 5c 00 41 00 62 00 63 00 2d 00 │ l·l·o·\·A·b·c·-· │
5a 00 48 00 2d 00 2d 4e 87 65 2d 00 41 00 62 00 │ Z·H·-·-N·e-·A·b· │
63 00 3b 00 43 00 3a 00 5c 00 47 00 6e 00 75 00 │ c·;·C·:·\·G·n·u· │
57 00 69 00 6e 00 33 00 32 00 5c 00 62 00 69 00 │ W·i·n·3·2·\·b·i· │

system_value在内存中的值(UTF8编码)

6d 33 32 3b   43 3a 5c 57   49 4e 44 4f   57 53 3b 63   │ m32;C:\WINDOWS;c │
3a 5c 48 65 6c 6c 6f 5c 41 62 63 2d 5a 48 2d e4 │ :\Hello\Abc-ZH-· │
b8 ad e6 96 87 2d 41 62 63 3b 43 3a 5c 47 6e 75 │ ·····-Abc;C:\Gnu │

补充3

utf8 最小代码单元是一个字节

utf16 的最小代码单元是2个字节

complication-database.json 导入clion无法正确编译

使用make compile-commands 生成 compilation-database.json

将其导入到clion中,出现编译错误,原因是因为json中的编译命令路径问题,需要把
\\\\\\ 替换为/,然后重新导入即可。

arguments.cpp 969 解析+-参数选项
1162 解析JVM -XX参数

ref

  1. jvm char*在内存中的存储方式为小端模式

  2. 查看字符编码

Unicode和UTF编码转换

  1. 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 默认实现类

主要匹配以下编译器


private static final Map<String, OCCompilerKind> compilerCache = MapsKt.mapOf(
new Pair[]{
TuplesKt.to("cl", MSVCCompilerKind.INSTANCE),
TuplesKt.to("gcc", GCCCompilerKind.INSTANCE),
TuplesKt.to("g++", GCCCompilerKind.INSTANCE),
TuplesKt.to("xgcc", GCCCompilerKind.INSTANCE),
TuplesKt.to("xg++", GCCCompilerKind.INSTANCE),
TuplesKt.to("colorgcc", GCCCompilerKind.INSTANCE),
TuplesKt.to("cc", GCCCompilerKind.INSTANCE),
TuplesKt.to("c++", GCCCompilerKind.INSTANCE),
TuplesKt.to("cpp", GCCCompilerKind.INSTANCE),
TuplesKt.to("clang", ClangCompilerKind.INSTANCE),
TuplesKt.to("clang++", ClangCompilerKind.INSTANCE),
TuplesKt.to("emcc", ClangCompilerKind.INSTANCE),
TuplesKt.to("em++", ClangCompilerKind.INSTANCE),
TuplesKt.to("tiarmclang", ClangCompilerKind.INSTANCE),
TuplesKt.to("nvcc", NVCCCompilerKind.INSTANCE),
TuplesKt.to(OCBuiltInCompilerKindProvider.CLANG_CL_ID, ClangClCompilerKind.INSTANCE),
TuplesKt.to("icl", MSVCCompilerKind.INSTANCE),
TuplesKt.to("icc", GCCCompilerKind.INSTANCE),
TuplesKt.to("icpc", GCCCompilerKind.INSTANCE),
TuplesKt.to("dpcpp-cl", ClangClCompilerKind.INSTANCE)
}
);

clion-compdb.jar

主要用于解析compile-commands.json

结构如下

[
{ "directory": "/home/user/llvm/build",
"arguments": ["/usr/bin/clang++", "-Irelative", "-DSOMEDEF=With spaces, quotes and \\-es.", "-c", "-o", "file.o", "file.cc"],
"file": "file.cc" },

{ "directory": "/home/user/llvm/build",
"command": "/usr/bin/clang++ -Irelative -DSOMEDEF=\"With spaces, quotes and \\-es.\" -c -o file.o file.cc",
"file": "file2.cc" },

...
]

当通过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) {
if (set.isEmpty()) {
return;
}
for (File compiler : set) {
String message = CompDBBundle.message("project.resolver.cannot.resolve.compiler.error", compiler);
Intrinsics.checkNotNullExpressionValue(message, "CompDBBundle.message(\"pr…ompiler.error\", compiler)");
listener.onTaskOutput(resolveTaskId, message + "\n", false);
CompDBLog.INSTANCE.getLOG().debug(message);
String compilerEventId = "unresolved-compiler:" + UUID.randomUUID();
OperationDescriptor taskOperationDescriptorImpl = new TaskOperationDescriptorImpl(message, System.currentTimeMillis(), "unresolved-compiler");
ExternalSystemProgressEvent externalSystemStartEventImpl = new ExternalSystemStartEventImpl(compilerEventId, parentEventId, taskOperationDescriptorImpl);
ExternalSystemProgressEvent externalSystemFinishEventImpl = new ExternalSystemFinishEventImpl(compilerEventId, parentEventId, taskOperationDescriptorImpl, new FailureResultImpl(externalSystemStartEventImpl.getEventTime(), externalSystemStartEventImpl.getEventTime(), CollectionsKt.listOf(new FailureImpl(message, message, CollectionsKt.emptyList()))));
listener.onStatusChange(new ExternalSystemTaskExecutionEvent(resolveTaskId, externalSystemStartEventImpl));
listener.onStatusChange(new ExternalSystemTaskExecutionEvent(resolveTaskId, externalSystemFinishEventImpl));
}
}

解决方法

找到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

GC垃圾回收器 调整参数

不同版本 OpenJDK 源码调试方案

WSL

在Ubuntu中编译和调试OpenJDK

编译 openJDK

Ubuntu下使用rpm

windows 平台编译openjdk12

tar教程

OpenJDK 编译指南(Ubuntu 16.04 + MacOS 10.15)

Cygwin

OpenJDK 编译指南(Ubuntu 16.04 + MacOS 10.15)

JBPM 4.0使用hibernate 3.6.0作为数据持久框架,该版本依赖的javassist版本为3.12.0.GA

Hibernate中的每个Entity其实都是代理过的类,由javassit生成一个代理类去继承Entity类。

举个例子

public class Phone {
}

@Entity
public class PhoneImpl extends Phone {
}

public class User {

@OneToOne
private Phone phone;

public Phone getPhone() {
return phone;
}

}

@Entity
public class UserImpl extends User {


@OneToOne
private PhoneImpl phone;

@Override
public PhoneImpl getPhone() {
return phone;
}

}

//javassit生成的代理类如下
public class UserImplProxy extends UserImpl {

private PhoneImpl phone;

private <T> T fetchDataFromDB() {
return (T) new Object();
}


@Override
public PhoneImpl getPhone() {
//hibernate 代理 查询数据库
phone = fetchDataFromDB();
return phone;
}

}
public class Test {

public static void main(String[] args) {
Method[] declaredMethods = UserImplProxy.class.getDeclaredMethods();

/**
*
* /**
* <init>()V 0x0001 [public]
* fetchDataFromDB()Ljava/lang/Object; 0x0002 [private]
* getPhone()Lcom/project/pangu/cache/PhoneImpl;0x0001 [public]
* getPhone()Lcom/project/pangu/cache/Phone; 0x1041 [public synthetic bridge]
*/
//此处模拟jbpm的调用
UserImplProxy proxy = new UserImplProxy();
PhoneImpl phoneImpl = proxy.getPhone();
System.out.println(1);
}
}

你会发现

执行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) {
Class[] ifs = clazz.getInterfaces();
for (int i = 0; i < ifs.length; i++)
getMethods(hash, ifs[i]);

Class parent = clazz.getSuperclass();
if (parent != null)
getMethods(hash, parent);

Method[] methods = SecurityActions.getDeclaredMethods(clazz);
for (int i = 0; i < methods.length; i++)
if (!Modifier.isPrivate(methods[i].getModifiers())) {
Method m = methods[i];
//重点,RuntimeSupport.makeDescriptor(m),这里返回格式为:方法参数表+方法返回类型;
String key = m.getName() + ':' + RuntimeSupport.makeDescriptor(m);
// JIRA JASSIST-85
// put the method to the cache, retrieve previous definition (if any)
Method oldMethod = (Method)hash.put(key, methods[i]);

// check if visibility has been reduced
if (null != oldMethod && Modifier.isPublic(oldMethod.getModifiers())
&& !Modifier.isPublic(methods[i].getModifiers()) ) {
// we tried to overwrite a public definition with a non-public definition,
// use the old definition instead.
hash.put(key, oldMethod);
}
}
}

Map的key最终格式为:methodName:paramsTypes+returnType

javassit 3.16.0.GA

private static void getMethods(HashMap hash, Class clazz, Set visitedClasses) {
if (visitedClasses.add(clazz)) {
Class[] ifs = clazz.getInterfaces();

for(int i = 0; i < ifs.length; ++i) {
getMethods(hash, ifs[i], visitedClasses);
}

Class parent = clazz.getSuperclass();
if (parent != null) {
getMethods(hash, parent, visitedClasses);
}

Method[] methods = SecurityActions.getDeclaredMethods(clazz);

for(int i = 0; i < methods.length; ++i) {
if (!Modifier.isPrivate(methods[i].getModifiers())) {
Method m = methods[i];
// //重点,RuntimeSupport.makeDescriptor(m),这里返回格式为:方法参数表;
String key = m.getName() + ':' + RuntimeSupport.makeDescriptor(m.getParameterTypes(), (Class)null);
Method oldMethod = (Method)hash.put(key, methods[i]);
if (null != oldMethod && Modifier.isPublic(oldMethod.getModifiers()) && !Modifier.isPublic(methods[i].getModifiers())) {
hash.put(key, oldMethod);
}
}
}

}
}

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());
PhoneImpl phoneImpl = proxy.getPhone();

所以导致jbmp执行相关操作时,查询对象实体时,有一定几率导致返回为空(没有被代理,那么就不会触发查询)

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/

https://lcu.vivide.re/#operation--lol-chat-v1-me-put

https://developer.riotgames.com/docs/lol

设置

为了观战韩服职业选手排位历史记录

  1. 下载外服客户端

  2. 修改配置

C:\ProgramData\Riot Games\Metadata\league_of_legends.live 目录下
找到league_of_legends.live.product_settings.yaml
修改如下

auto_patching_enabled_by_player: false
dependencies:
Direct X 9:
hash: "9f22c993a42816d61a3063badbf25f9dd299721051ca0665a7cb295ba97591b0"
phase: "Succeeded"
version: "1.0.0"
locale_data:
available_locales: # 配置语言选项
- "en_US" #英文
- "zh_CN" #中文
- "ko_KR" #韩文
- "ja_JP" #日文
default_locale: "en_US" #默认语言
patching_policy: "manual"
patchline_patching_ask_policy: "ask"
product_install_full_path: "G:\\Riot Games\\League of Legends"
product_install_root: "G:/Riot Games"
settings:
create_shortcut: false
create_uninstall_key: true
locale: "ko_KR" # 这里设置为你想要的语言,参考上面
shortcut_name: "League of Legends.lnk"
should_repair: false

为了ob韩服不乱码,所以需要将上述的locale 后面的值改成ko_KR

  1. 修改观战进程语言

找到 LOL 安装目录 ,这里以我的为例,G:\Riot Games\League of Legends\Config
打开 LeagueClientSettings.yaml 文件,
修改如下

install:
crash_reporting:
enabled: true
type: "crashpad"
game-settings:
accountId: 238191481
modified: false
timestamp: 0
gameflow-patcher-lock: null
gameflow-process-info: null
gameflow-spectate-reconnect-info: null
globals:
locale: "en_US" # 这里设置为ko_KR 就不会乱码了
region: "NA"
lcu-settings:
accountId: 238191481
modified: true
timestamp: 0
patcher:
client_migrated: true
client_patcher_available: true
game_migrated: true
game_patcher_available: true
locales:
- "en_US"
- "ja_JP"
- "ko_KR"
toggles:
new_client_patcher: 0
new_game_patcher: 0
perks-settings:
accountId: 238191481
modified: false
timestamp: 0
riotclient-upgrade:
seq-success-count: 16
success-count: 16
rso-auth:
install-identifier: "7ca3c8997368594881546f6d2d70a551"


准备工作

  1. 配置环境变量 SSLKEYLOGFILE 值为拥有读写权限的文件,例如:D:\A_TLS_LOG\sslkeylog.log

  2. 打开wireshark,找到首选项(ctrl+shift+p),Protocols >> TLS ,TLS debug file 配置tls日志,(Pre)-Master-Secret log filename配置上述环境变量SSLKEYLOGFILE中指定的文件

概论

计算中的任何数据都是由二进制表示,因为IC(Integrated Circuit)集成电路的引脚只有直流电压0V5V两个状态,也就是一个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))

以下数取反后的值
10 -11
1 -2
-2 1
-5 4
-6 5

位移

只有右移时才能区分出逻辑位移算术位移

java中 >> 为算术右移,>>> 为逻辑位移

int x = -4;
int y = -4 >>2;// -1
int z = -4 >>>2; // 1073741823

逻辑位移

补零就行了

算术位移

将二进制数作为带符号的数值进行运算时,移位后需要在最高位补充符号位(0或者1)

浮点数

符号、尾数、基数、指数

双精度(64bit)

符号部分(1bit) + 指数部分(11bit) + 尾数部分(52bit)

单精度(32bit)

符号部分(1bit) + 指数部分(8bit) + 尾数部分(23bit)

sds (Simple dynamic string)

sdsHeader

sdsHdr{
size_t len;
size_t alloc;
size_t flag
char [] buf;//柔性数组,内存分配时不占用空间,根据需要可以动态构建该区域,且内存空间连续
}

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
$3
set
$4
test
$3
abc

翻译成人话就是:三个字符串,分别为set test abc

dictht (HashTable)

其他

//设置状态
flags |= STATE_OEPN

//取消状态
flags &= ~STATE_OPEN

void updateFlag(int*flags,int flag,int enable){
if(enable){
*flags |= flag;
}else{
*flags &= ~flag;
}
}

自动配置

@EnableTransactionManagement
-> @Import(TransactionManagementConfigurationSelector.class)
-> ProxyTransactionManagementConfiguration

ProxyTransactionManagementConfiguration
@Bean
-> BeanFactoryTransactionAttributeSourceAdvisor
->setTranactionAttributeSource (TransactionAttributeSource())
->setAdvice(TransactionInterceptor()->ref->TransactionManager)

    7vPUtZJ6pMgebJvzi4C,eWDpdRrVLwQk56uCCIE
0%