Conversation
# Conflicts: # core/pom.xml # pom.xml
|
缺少测试,有冲突需要解决。 |
# Conflicts: # core/src/main/java/com/taobao/arthas/core/GlobalOptions.java # core/src/test/java/com/taobao/arthas/core/command/express/OgnlTest.java
| * 是否切换使用表达式ognl/qlexpress开关 | ||
| */ | ||
| @Option(level = 1, | ||
| name = "express-type", |
There was a problem hiding this comment.
是不是可以考虑短一点,比如就缩写成 el(expression language)
| * qlexpress使用参数 | ||
| */ | ||
| @Option(level = 1, | ||
| name = "qlexpress-config", |
There was a problem hiding this comment.
这么复杂的东西暂时没必要交给用户设置吧。我们直接给一个最推荐的就行了,没必要暴露给用户,毕竟这个场景比较单一,给个通用配置就够了
| public QLExpress(ClassSupplier classResolver) { | ||
| initQLExpress(classResolver); | ||
| initConfig(); | ||
| initContext(); |
There was a problem hiding this comment.
其实这三个函数就是分别初始化三个成员变量,下面这种写法可能更加清晰:
this.expressRunner = initQLExpress(classResolver);
this.qlOptions = initConfig();
this.qlGlobalContext = initContext();尽量不要使用有副作用的函数
|
|
||
| @Override | ||
| public Express bind(String name, Object value) { | ||
| qlGlobalContext.put(name, value); |
There was a problem hiding this comment.
个人觉得在 put 的时候加上 "#" 前缀,要比 get 的时候 replace 要好。这样 context 的逻辑更加简单纯粹。replace 可能会导致改变不该改变的字符。
|
|
||
| public void clear() { | ||
| context.clear(); | ||
| this.context.put("reflectLoader",reflectLoader); |
| if ((this.reflectLoader != null) && (this.object != null) && !variableName.startsWith("#")) { | ||
| return this.reflectLoader.loadField(this.object, variableName, true, PureErrReporter.INSTANCE); | ||
| } | ||
| String newVariableName = variableName.replace("#",""); |
There was a problem hiding this comment.
个人觉得在 put 的时候加上前缀,比 get 的时候隐藏一个 # 替换逻辑要更好
| @Override | ||
| public Value get(Map<String, Object> attachments, String variableName) { | ||
| if ((this.reflectLoader != null) && (this.object != null) && !variableName.startsWith("#")) { | ||
| return this.reflectLoader.loadField(this.object, variableName, true, PureErrReporter.INSTANCE); |
There was a problem hiding this comment.
这个 api 有点底层,可以考虑继承 ObjectFieldExpressContext,然后额外加一个 map 功能,而不是直接调用 reflectLoader。或者我直接在 Express4Runner 上开个 api
| + " ognl -c 5d113a51 '@com.taobao.arthas.core.GlobalOptions@isDump' \n" | ||
| + Constants.WIKI + Constants.WIKI_HOME + "ognl\n" | ||
| + " https://commons.apache.org/proper/commons-ognl/language-guide.html") | ||
| + " ognl '@java.lang.System@out.println(\"hello \\u4e2d\\u6587\")' \n" |
There was a problem hiding this comment.
是不是也得有一个类似 ognl 这样的纯执行 qlexpress 表达式的命令
site/docs/en/doc/options.md
Outdated
| | verbose | false | This option enables print verbose information | | ||
| | strict | true | whether to enable strict mode | | ||
|
|
||
| | express-type | ognl | Option to use ognl/qlexpress in commands, default ognl, can change to qlexpress | |
There was a problem hiding this comment.
上次讨论的这个选项的名称是否考虑短一点,比如叫做 el,这样避免用户在使用 qle 时敲的命令太长
There was a problem hiding this comment.
例子可以加一些有特色的,能解决具体问题的,比如复杂对象构造,list新建等等
|
可以再举一个复杂对象构造的例子。 |
# Conflicts: # core/src/main/java/com/taobao/arthas/core/GlobalOptions.java
# Conflicts: # core/src/main/java/com/taobao/arthas/core/GlobalOptions.java
There was a problem hiding this comment.
Pull Request Overview
This PR introduces support for QLExpress 4.0 as an alternative expression engine to OGNL in Arthas. The implementation adds a new qlexpress command and allows users to switch the default expression language through a global option.
Key changes:
- Added QLExpress 4.0 dependency and integration classes
- Implemented new
qlexpresscommand with similar functionality to the existingognlcommand - Added global option
elto switch between OGNL and QLExpress engines - Updated documentation to reflect the new expression language options
Reviewed Changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pom.xml | Added QLExpress 4.0 dependency |
| core/pom.xml | Added QLExpress 4.0 dependency with duplicate OGNL entry |
| GlobalOptions.java | Added el option to switch expression languages |
| ExpressFactory.java | Modified to support both OGNL and QLExpress based on global option |
| QLExpressCommand.java | New command implementation for QLExpress functionality |
| QLExpress*.java | Supporting classes for QLExpress integration |
| BuiltinCommandPack.java | Registered new QLExpress command |
| site/docs/* | Updated documentation for new expression language option |
Comments suppressed due to low confidence (1)
site/docs/en/doc/options.md:10
- [nitpick] The table formatting appears inconsistent. The original formatting with spaces should be maintained for better readability:
| ---------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|------------------------| ------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
core/pom.xml
Outdated
| <dependency> | ||
| <groupId>ognl</groupId> | ||
| <artifactId>ognl</artifactId> | ||
| </dependency> |
There was a problem hiding this comment.
There appears to be a duplicate OGNL dependency declaration. The OGNL dependency is already declared at line 211-213, making this additional declaration redundant.
| <dependency> | |
| <groupId>ognl</groupId> | |
| <artifactId>ognl</artifactId> | |
| </dependency> |
| import com.taobao.arthas.core.command.express.ExpressFactory; | ||
| import com.taobao.arthas.core.command.model.ClassLoaderVO; | ||
| import com.taobao.arthas.core.command.model.ObjectVO; | ||
| import com.taobao.arthas.core.command.model.OgnlModel; |
There was a problem hiding this comment.
The import for OgnlModel is unused in this class. Since this class uses QLExpressModel instead, this import should be removed.
| import com.taobao.arthas.core.command.model.OgnlModel; |
| import com.taobao.arthas.core.GlobalOptions; | ||
| import com.taobao.arthas.core.advisor.Advice; | ||
| import com.taobao.arthas.core.command.model.ExpressTypeEnum; | ||
| import ognl.OgnlException; |
There was a problem hiding this comment.
The import for OgnlException appears incorrect for a QLExpress test class. The test methods declare throwing OgnlException but should likely throw ExpressException instead.
| import ognl.OgnlException; |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@hengyunabc 周末我对泄露问题进行了排查,结论如下。 TLDR:ArthasClassloader 的泄露和表达式引擎无关,根因是 Arthas 的在退出时没有对 ThreadLocal 进行清理,ArthasClassloader加载的相关对象泄露在了业务线程的 泄露的对象包括:
下面是我在复现该问题后,堆栈分析的证据截图:
建议该问题单独提一个 PR 修复,见 #3077 。 |
Co-authored-by: taokankan.tk <taokan1991@aliyun.com> Co-authored-by: DQYuan <932087612@qq.com>






背景链接:
Proposal: 表达式体验优化与引擎更换 #2849
改动实现:
新增了qlexpress自己的command,命令名称 qlexpress
参数说明
使用参考:
$ qlexpress 'java.lang.System.out.println("hello~")'通过 hashcode 指定 ClassLoader:
$classloader -t +-BootstrapClassLoader +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@301ec38b +-com.taobao.arthas.agent.ArthasClassloader@472067c7 +-jdk.internal.loader.ClassLoaders$AppClassLoader@4b85612c +-org.springframework.boot.loader.LaunchedURLClassLoader@7f9a81e8$ qlexpress -c 7f9a81e8 org.springframework.boot.SpringApplication.logger注意 hashcode 是变化的,需要先查看当前的 ClassLoader 信息,提取对应 ClassLoader 的 hashcode。
对于只有唯一实例的 ClassLoader 可以通过 class name 指定,使用起来更加方便:
$ qlexpress --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader org.springframework.boot.SpringApplication.logger和ognl相比语法的区别
option中新增"el"属性配置,支持切换ognl语法为qlexpress

使用语言切换成qlexpress
$ option el qlexpress对于观察表达式,获取观测数据的方法:
OGNL:
{params, target, returnObj}QLEXPRESS:
[params, target, returnObj]常用用法举例
OGNL语法
$ watch demo.MathGame primeFactors '{params, returnObj}' '#cost>200' -x 2QLEXPRESS4语法
$ watch demo.MathGame primeFactors '[params, returnOb]' 'cost>200' -x 2更多qlexpress4.0语法链接
https://github.com/alibaba/QLExpress/tree/v4.0.0-beta.1