英文:
Eclipse MAT OQL list of classes in a certain package
问题
使用Eclipse MAT 1.9.1 OQL
我想列出堆转储中特定包中的所有类。
我正在尝试以下查询:
SELECT c.getName() as name, c.getName().indexOf("com.mycompany") as idx FROM java.lang.Class c WHERE idx > 0
得到以下结果:
java.lang.NullPointerException: idx at
org.eclipse.mat.parser.internal.oql.compiler.Operation$GreaterThan.evalNull(Operation.java:232)
at
org.eclipse.mat.parser.internal.oql.compiler.Operation$RelationalOperation.compute(Operation.java:92)
at
org.eclipse.mat.parser.internal.oql.OQLQueryImpl.accept(OQLQueryImpl.java:1161)
at
org.eclipse.mat.parser.internal.oql.OQLQueryImpl.accept(OQLQueryImpl.java:1151)
at
org.eclipse.mat.parser.internal.oql.OQLQueryImpl.filterClasses(OQLQueryImpl.java:1133)
at
org.eclipse.mat.parser.internal.oql.OQLQueryImpl.doFromItem(OQLQueryImpl.java:921)
at
org.eclipse.mat.parser.internal.oql.OQLQueryImpl.internalExecute(OQLQueryImpl.java:690)
at
org.eclipse.mat.parser.internal.oql.OQLQueryImpl.execute(OQLQueryImpl.java:667)
at org.eclipse.mat.inspections.OQLQuery.execute(OQLQuery.java:52) at
org.eclipse.mat.inspections.OQLQuery.execute(OQLQuery.java:1) at
org.eclipse.mat.query.registry.ArgumentSet.execute(ArgumentSet.java:132)
at
org.eclipse.mat.ui.snapshot.panes.OQLPane$OQLJob.doRun(OQLPane.java:468)
at
org.eclipse.mat.ui.editor.AbstractPaneJob.run(AbstractPaneJob.java:34)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:60)
请建议。
英文:
using Eclipse MAT 1.9.1 OQL
I want to list all the classes in the heap dump in a certain package.
I am trying the query:
SELECT c.getName() as name, c.getName().indexOf("com.mycompany") as idx FROM java.lang.Class c WHERE idx > 0
getting:
> java.lang.NullPointerException: idx at
> org.eclipse.mat.parser.internal.oql.compiler.Operation$GreaterThan.evalNull(Operation.java:232)
> at
> org.eclipse.mat.parser.internal.oql.compiler.Operation$RelationalOperation.compute(Operation.java:92)
> at
> org.eclipse.mat.parser.internal.oql.OQLQueryImpl.accept(OQLQueryImpl.java:1161)
> at
> org.eclipse.mat.parser.internal.oql.OQLQueryImpl.accept(OQLQueryImpl.java:1151)
> at
> org.eclipse.mat.parser.internal.oql.OQLQueryImpl.filterClasses(OQLQueryImpl.java:1133)
> at
> org.eclipse.mat.parser.internal.oql.OQLQueryImpl.doFromItem(OQLQueryImpl.java:921)
> at
> org.eclipse.mat.parser.internal.oql.OQLQueryImpl.internalExecute(OQLQueryImpl.java:690)
> at
> org.eclipse.mat.parser.internal.oql.OQLQueryImpl.execute(OQLQueryImpl.java:667)
> at org.eclipse.mat.inspections.OQLQuery.execute(OQLQuery.java:52) at
> org.eclipse.mat.inspections.OQLQuery.execute(OQLQuery.java:1) at
> org.eclipse.mat.query.registry.ArgumentSet.execute(ArgumentSet.java:132)
> at
> org.eclipse.mat.ui.snapshot.panes.OQLPane$OQLJob.doRun(OQLPane.java:468)
> at
> org.eclipse.mat.ui.editor.AbstractPaneJob.run(AbstractPaneJob.java:34)
> at org.eclipse.core.internal.jobs.Worker.run(Worker.java:60)
Please advise.
答案1
得分: 3
以下是您要翻译的内容:
有几个问题存在于这个查询中。idx
在 SELECT c.getName() as name, c.getName().indexOf("com.mycompany") as idx FROM java.lang.Class c WHERE idx > 0
中是一个列名,因此不可见于 WHERE
子句。
OQL 首先评估 FROM
子句,选择对象列表,然后 c
变量可见于 WHERE
子句,其中会检查每个对象是否将传递给 SELECT
子句。
因此,请尝试:
SELECT c.getName() as name, c.getName().indexOf("com.mycompany") as idx FROM java.lang.Class c WHERE c.getName().indexOf("com.mycompany") > 0
但是由于以下原因,它会失败:
报告的问题:
在对象 java.lang.Class [id=0x6c027f2c8] 中未找到 getName() 方法,类型为 org.eclipse.mat.parser.model.InstanceImpl
因为堆转储中的某些 java.lang.Class 对象实际上不是普通的可以有实例的类,而是 java.lang.Class 类型的普通对象实例。听起来很奇怪,但这些对象是 `byte`、`short`、`int`、`long`、`float`、`double`、`char`、`boolean`、`void`。它们只用于反映类和方法 - 但这些类的实例不能存在。
在 MAT 中,堆转储中的对象表示为 `org.eclipse.mat.snapshot.model.IObject`,其中一些也是子类型 `org.eclipse.mat.snapshot.model.IClass`。我们需要排除上述 9 个特殊对象。我已将您的查询更改为查找 com.sun,因为我的转储中不会有 com.mycompany 对象。
SELECT c.getName() AS name, c.getName().indexOf("com.sun") AS idx
FROM java.lang.Class c
WHERE ((c implements org.eclipse.mat.snapshot.model.IClass) and (c.getName().indexOf("com.sun") > 0))
这仍然无法正常工作,因为如果类名以 'com.sun' 开头,索引将为 0,会导致测试失败。更改测试运算符:
SELECT c.getName() AS name, c.getName().indexOf("com.sun") AS idx
FROM java.lang.Class c
WHERE ((c implements org.eclipse.mat.snapshot.model.IClass) and (c.getName().indexOf("com.sun") >= 0))
现在这可以正常工作并找到一些类。
我们可以通过使用属性表示法稍微简化查询,其中 @val 是 bean 内省,相当于 getVal()。
SELECT c.@name AS name, c.@name.indexOf("com.sun") AS idx
FROM java.lang.Class c
WHERE ((c implements org.eclipse.mat.snapshot.model.IClass) and (c.getName().indexOf("com.sun") >= 0))
<details>
<summary>英文:</summary>
There are several things wrong with that query. `idx` in
`SELECT c.getName() as name, c.getName().indexOf("com.mycompany") as idx FROM java.lang.Class c WHERE idx > 0` is a column name, so is not visible to the `WHERE` clause.
OQL evaluates the `FROM` clause first selecting a list of objects, then the `c` variable is visible to the `WHERE` clause where each of the objects is examined to see if it will be passed to the `SELECT` clauses.
So try:
SELECT c.getName() as name, c.getName().indexOf("com.mycompany") as idx FROM java.lang.Class c WHERE c.getName().indexOf("com.mycompany") > 0
but that fails for the reason:
Problem reported:
Method getName() not found in object java.lang.Class [id=0x6c027f2c8] of type org.eclipse.mat.parser.model.InstanceImpl
because some java.lang.Class objects in the heap dump are in fact not ordinary classes which could have instances, but plain object instances of type java.lang.Class. That sounds odd, but those objects are `byte`,`short`,`int`,`long`,`float`,`double`,`char`,`boolean`,`void`. They are just used to describe classes and methods for reflection - but instances of those can't exist.
Inside of MAT objects in the heap dump are represented as
`org.eclipse.mat.snapshot.model.IObject` and some are also of a subtype `org.eclipse.mat.snapshot.model.IClass`. We need to exclude those 9 special objects above. I've changed your query to look for com.sun as my dumps won't have com.mycompany objects.
SELECT c.getName() AS name, c.getName().indexOf("com.sun") AS idx
FROM java.lang.Class c
WHERE ((c implements org.eclipse.mat.snapshot.model.IClass) and (c.getName().indexOf("com.sun") > 0))
This still doesn't work, because if the class name starts with 'com.sun' the index will be 0 and will fail the test. Change the test operator:
SELECT c.getName() AS name, c.getName().indexOf("com.sun") AS idx
FROM java.lang.Class c
WHERE ((c implements org.eclipse.mat.snapshot.model.IClass) and (c.getName().indexOf("com.sun") >= 0))
This now works and finds some classes.
We can simplify the query a little by using attribute notation, where @val is a bean introspection which is the equivalent of getVal().
SELECT c.@name AS name, c.@name.indexOf("com.sun") AS idx
FROM java.lang.Class c
WHERE ((c implements org.eclipse.mat.snapshot.model.IClass) and (c.getName().indexOf("com.sun") >= 0))
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论