活用ognl表达式

转载:https://github.com/alibaba/arthas/issues/11

前言

Arthas 3.0中使用ognl表达式替换了groovy来实现表达式的求值功能,解决了groovy潜在会出现内存泄露的问题。灵活运用ognl表达式,能够极大提升问题排查的效率。

ognl官方文档:https://commons.apache.org/proper/commons-ognl/language-guide.html

一个测试应用

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;/*** @author zhuyong on 2017/9/13.*/
public class Test {public static final Map m = new HashMap<>();public static final Map n = new HashMap<>();static {m.put("a", "aaa");m.put("b", "bbb");n.put(Type.RUN, "aaa");n.put(Type.STOP, "bbb");}public static void main(String[] args) throws InterruptedException {List<Pojo> list = new ArrayList<>();for (int i = 0; i < 40; i ++) {Pojo pojo = new Pojo();pojo.setName("name " + i);pojo.setAge(i + 2);list.add(pojo);}while (true) {int random = new Random().nextInt(40);String name = list.get(random).getName();list.get(random).setName(null);test(list);list.get(random).setName(name);Thread.sleep(1000l);}}public static void test(List<Pojo> list) {}public static void invoke(String a) {System.out.println(a);}static class Pojo {String name;int age;String hobby;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getHobby() {return hobby;}public void setHobby(String hobby) {this.hobby = hobby;}}
}public enum Type {RUN, STOP;
}

查看第一个参数

params是参数列表,是一个数组,可以直接通过下标方式访问

$ watch Test test params[0] -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 26 ms.
@ArrayList[@Pojo[Test$Pojo@6e2c634b],@Pojo[Test$Pojo@37a71e93],@Pojo[Test$Pojo@7e6cbb7a],...
]

查看数组中的元素

第一个参数是一个List,想要看List中第一个Pojo对象,可以通过下标方式,也可以通过List的get方法访问。

$ watch Test test params[0][0] -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 14 ms.
@Pojo[name=@String[name 0],age=@Integer[2],hobby=null,
]$ watch Test test params[0].get(0) -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 14 ms.
@Pojo[name=@String[name 0],age=@Integer[2],hobby=null,
]

查看Pojo的属性

拿到这个Pojo可以,直接访问Pojo的属性,如age

$ watch Test test params[0].get(0).age -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 21 ms.
@Integer[2]

还可以通过下标的方式访问params[0][0]["age"],这个写法等效于params[0][0].age

$ watch Test test params[0][0]["name"] -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 53 ms.
watch failed, condition is: null, express is: params[0][0][age], ognl.NoSuchPropertyException: com.taobao.arthas.core.advisor.Advice.age, visit /Users/wangtao/logs/arthas/arthas.log for more details.

但这样会报错,这时候需要再加一个引号

$ watch Test test 'params[0][0]["age"]' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 25 ms.
@Integer[2]

集合投影

有时候我们只需要抽取对象数组中的某一个属性,这种情况可以通过投影来实现,比如要将Pojo对象列表中的name属性单独抽出来,可以通过params[0].{name}这个表达式来实现。 ognl会便利params[0]这个List取出每个对象的name属性,重新组装成一个新的数组。用法相当于Java stream中的map函数。

$ watch Test test params[0].{name} -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 56 ms.
@ArrayList[@String[name 0],@String[name 1],@String[name 2],@String[name 3],null,@String[name 5],@String[name 6],@String[name 7],@String[name 8],@String[name 9],
]

集合过滤

有时候还需要针对集合对象按某种条件进行过滤,比如想找出所有age大于5的Pojo的name,可以这样写

$ watch Test test "params[0].{? #this.age > 5}.{name}" -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 25 ms.
@ArrayList[@String[name 4],@String[name 5],@String[name 6],null,@String[name 8],@String[name 9],
]

其中{? #this.age > 5} 相当于stream里面的filter,后面的name相当于stream里面的map

那如果要找到第一个age大于5的Pojo的name,怎么办呢?可以用^$来进行第一个或最后一个的匹配,像下面这样:

$ watch Test test "params[0].{^ #this.age > 5}.{name}" -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 24 ms.
@ArrayList[@String[name 4],
]
Command hit execution time limit 1, therefore will be aborted.
$ watch Test test "params[0].{$ #this.age > 5}.{name}" -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 43 ms.
@ArrayList[@String[name 9],
]

多行表达式

有些表达式一行之内无法表达,需要多行才能表达,应该怎么写的?比如,假设我们要把所有Pojo的name拿出来,再往里面新加一个新的元素,在返回新的列表,应该如何写?可以通过中括号将多个表达式串联起来,最后一个表达式的返回值代表整个表达式的最终结果。临时变量可以用#来表示。

$ watch Test test '(#test=params[0].{name}, #test.add("abc"), #test)' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 28 ms.
@ArrayList[@String[name 0],@String[name 1],@String[name 2],@String[name 3],@String[name 4],@String[name 5],@String[name 6],@String[name 7],@String[name 8],null,@String[abc],
]

调用构造函数

调用构造函数,必须要指定要创建的类的全类名。比如下面的例子中,创建一个新的list,然后添加一个新的元素,然后返回添加后的list。

$ watch Test test '(#test=new java.util.ArrayList(), #test.add("abc"), #test)' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 37 ms.
@ArrayList[@String[abc],
]

访问静态变量

可以通过@class@filed方式访问,注意需要填写全类名

$ watch Test test '@Test@m' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 35 ms.
@HashMap[@String[a]:@String[aaa],@String[b]:@String[bbb],
]

调用静态方法

可以通过@class@method(args)方式访问,注意需要填写全类名

$ watch Test test '@java.lang.System@getProperty("java.version")' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 42 ms.
@String[1.8.0_51]

静态方法和非静态方法结合,例如想要获取当前方法调用的TCCL,可以像下面这样写:

$ watch Test test '@java.lang.Thread@currentThread().getContextClassLoader()' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 84 ms.
@AppClassLoader[ucp=@URLClassPath[sun.misc.URLClassPath@4cdbe50f],$assertionsDisabled=@Boolean[true],
]

访问Map中的元素

Test.n是一个HashMap,假设要获取这个Map的所有key,ongl针对Map接口提供了keysvalues这两个虚拟属性,可以像普通属性一样访问。

$ watch Test test '@Test@n.keys' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 57 ms.
@KeySet[@Type[RUN],@Type[STOP],
]

因为这个Map的Key是一个Enum,假设要把key为RUN这个值的value取出来应该怎么写呢?可以通过Enum的valueOf方法来创建一个Enum,然后get出来,比如下面一样

$ watch Test test '@Test@n.get(@Type@valueOf("RUN"))' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 168 ms.
@String[aaa]

或者是下面这样,通过迭代器+过滤的方式:

$ watch Test test '@Test@n.entrySet().iterator.{? #this.key.name() == "RUN"}' -n 1
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 72 ms.
@ArrayList[@Node[RUN=aaa],
]

附录: ognl内置的ognl的虚拟属性

  • Collection:
    • size
    • isEmpty
  • List:
    • iterator
  • Map:
    • keys
    • values
  • Set:
    • iterator
  • Iterator:
    • next
    • hasNext
  • Enumeration:
    • next
    • hasNext
    • nextElement
    • hasMoreElements

最后

欢迎在留言区分享你的牛逼用法,互相交流进步~

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497577.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jeff Dean晒Google Brain团队2017成绩单!

来源&#xff1a;全球人工智能谷歌大脑负责人 Jeff Dean 今天发文晒AutoML、语言理解、机器学习算法、机器学习系统等核心研究工作成绩单&#xff0c;全面总结谷歌大脑在2017年取得的成绩。一、自动化机器学习&#xff08;AutoML&#xff09;我们开发了使用强化学习和进化算法设…

mysql恢复主服务器_MySQL 5.6主从复制第二部分[恢复某一台从服务器]

MySQL 5.6主从复制第二部分[恢复某一台从服务器]&#xff0c;本来第二部分是想测试主服务器挂掉&#xff0c;提升从服务器的情况&#xff0c;可是出了点点意外&#xff0c;改本来第二部分是想测试主服务器挂掉&#xff0c;提升从服务器的情况&#xff0c;可是出了点点意外&…

亮相2018CES:解读阿里云IoT筹谋全球物联网市场的一盘大棋!

来源&#xff1a;阿里巴巴概要&#xff1a;近年来国内物联网市场高歌猛进&#xff0c;2017年也被称为物联网真正意义上的元年。成立还不到一年的阿里云IoT&#xff0c;以平台、市场、标准三位一体的策略&#xff0c;迅速在物联网领域崭露头角、稳固地位。一年一度的CES在拉斯维…

CompletableFuture 异步编程

本文从实例出发&#xff0c;介绍 CompletableFuture 基本用法。不过讲的再多&#xff0c;不如亲自上手练习一下。所以建议各位小伙伴看完&#xff0c;上机练习一把&#xff0c;快速掌握 CompletableFuture。 全文摘要&#xff1a; Future VS CompletableFuture CompletableFu…

java 线程 api_Java核心API之线程(上)

实例代码如下&#xff1a;package ThreadDemo;class RunnableDemo implements Runnable {private Thread t;private String threadName;RunnableDemo( String name) {threadName name;System.out.println("Creating " threadName );}public void run() {System.ou…

麦肯锡:物联网九大应用潜力无限 2025年经济价值高达11.1万亿美元

来源&#xff1a;WPR概要&#xff1a;物联网有可能从根本上改变人类与周围世界的互动方式。如果一切顺利的话&#xff0c;那么到2025年&#xff0c;物联网——将实体和数字世界连接起来的这项技术&#xff0c;其经济价值可达每年11&#xff0e;1万亿美元。物联网有可能从根本上…

线程池原理——生产者/消费者

import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue;/*** 简化的线程池&#xff0c;仅用来说明工作原理.<br>* author gongqiang <br>* version 1.0.0 2021年6月9日…

java程序移植_java JDBC 提高程序可移植性

介绍jdbc一般的程序: 【程序编程相关:jboracleweblogic c】很多java初学者在开始接触jdbc编程的时候,在网上与大部分的教材上都是这样 【推荐阅读:Java线程入门——什么是线程】import java.sql.*; 【扩展信息:关于J2ME与C#通过HTTP进行通信时】//可以运行的完整程序public cla…

致开发者:2018年AI技术趋势展望

来源&#xff5c;公众号“AI 前线”&#xff0c;&#xff08;ID&#xff1a;ai-front&#xff09;译者&#xff5c;核子可乐编辑&#xff5c;Emily概要&#xff1a;在 2018 年&#xff0c;开发者如何将一系列 AI 技术成果应用于当前的工作当中呢&#xff1f;近日&#xff0c;一…

svn java注释_svn 强制用户添加注释 和 允许用户修改注释

当我们用TortoiseSVN提交代码时&#xff0c;有很多人不喜欢写注释&#xff0c;导致以后代码版本多&#xff0c;也不清楚哪个版本到底改了什么东西。所以在提交的时候&#xff0c;我会强制要求添加注释。这是如何实现的&#xff1f;这个话题就涉及到了svn的Hooks功能的使用。所谓…

CES2018:英特尔披露量子计算和神经拟态计算研究最新进展

来源&#xff1a;科学网概要&#xff1a;今年上半年&#xff0c;英特尔计划与顶级院校和研究机构共享Loihi测试芯片&#xff0c;同时将其应用于解决更加复杂的数据集和问题。1月8日&#xff0c;在拉斯维加斯举办的2018年国际消费电子产品展&#xff08;CES&#xff09;上&#…

EDA风格与Reactor模式

来源&#xff1a;https://www.cnblogs.com/ivaneye/p/10129896.html 本文将探讨如下几个问题&#xff1a; Event-Driven架构风格的约束EDA风格对架构属性的影响Reactor架构模式Reactor所解决的问题redis中的EventDriven 从观察者模式到EDA风格 GOF的23种设计模式中&#xff…

sha java实现_关于Java实现SHA算法加密 @杨章隐

首先我们在实际开发过程中肯定是需要对明文密码进行加密的&#xff0c;这样&#xff0c;就算密码被获取&#xff0c;他们获取到的也是一串乱码。而目前主流的加密算法有MD5和SHA&#xff0c;这篇文章就带你来实现SHA加密import java.math.BigInteger;import java.security.Mess…

神经尘埃、脑波打字…… 2018年的脑科学要研究什么?

来源&#xff1a;科技日报概要&#xff1a;21世纪是脑科学时代。为了进一步了解大脑&#xff0c;监测大脑活动的研究进行得如火如荼&#xff0c;已在学术界和商业界掀起一股淘金热。人脑可谓人体最复杂、最神秘的器官&#xff0c;无数科学家殚精竭虑&#xff0c;也不过才揭开其…

webapp入门到实战_web前端入门到实战:前端高手在CSS 开发效率的必备片段

这篇文章会记录我们平时常用到的 CSS 片段&#xff0c;使用这些 CSS 可以帮助我们解决许多实际项目问题中遇到的&#xff0c;墙裂建议点赞收藏再看&#xff0c;方便日后查找清除浮动浮动给我们的代码带来的麻烦&#xff0c;想必不需要多说&#xff0c;我们会用很多方式来避免这…

FutureTask 示例

1、简单示例 2、泡茶 1、简单示例 // 创建 FutureTask FutureTask<Integer> futureTask new FutureTask<>(()-> 12); // 创建并启动线程 Thread t1 new Thread(futureTask); t1.start();// 获取计算结果(阻塞主线程&#xff0c;等待结果...) Integer result…

机器学习必知的8大神经网络架构和原理

来源&#xff1a;全球人工智能概要&#xff1a;有些任务直接编码较为复杂&#xff0c;我们不能处理所有的细微之处和简单编码&#xff0c;因此&#xff0c;机器学习很有必要。为什么需要机器学习&#xff1f;有些任务直接编码较为复杂&#xff0c;我们不能处理所有的细微之处和…

《科学》盘点2018可能被聚焦的研究领域

来源&#xff1a;科学网 概要&#xff1a;随着这些大趋势展现出来&#xff0c;《科学》杂志预测了今年可能被聚焦的关于研究和政策的特定领域。动荡的政治变革将在新的一年塑造科学的进程。美国总统唐纳德特朗普领导的政府预计将继续致力于废除基于科学的环境法规。英国离开欧盟…

Hamcrest匹配器常用方法总结

一.Hamcrest是什么&#xff1f; Hamcrest is a library of matchers, which can be combined in to create flexible expressions of intent in tests. Hamcrest 是一个为了测试为目的&#xff0c;且能组合成灵活表达式的匹配器类库。 二.Hamcrest jar包 hamcrest-core.jar -…

谷歌大脑2017总结下篇:从医疗、机器人等6个领域开始的改变世界之旅

作者&#xff1a;camel概要&#xff1a;Jeff Dean发表了这篇博文的下篇&#xff0c;内容包括谷歌大脑在 AI 应用方面&#xff08;诸如医疗、机器人、创新、公平和包容等&#xff09;的工作。昨天谷歌大脑&#xff08;Google Brain&#xff09;负责人 Jeff Dean 在 Google Resea…