根据文档,我可以用来-
从搜索 API 中排除某些内容......我对其进行了测试,例如,这适用于语言领域,但不适用于主题。
根据文档:
注意 cat stars:>10 -language:javascript 匹配包含超过 10 个星但不是用 JavaScript 编写的单词“cats”的存储库。
但是如果我想搜索cats stars:>10 -topic:javascript
它就不再工作了,尽管我测试了它并且恰好有 9 个存储库javascript
作为主题。
所以
cats stars:>10
返回 714 个结果
cats stars:>10 -topic:javascript
返回 714 个结果(-
不起作用)
cats stars:>10 +topic:javascript
返回 9 个结果
cats stars:>10 -language:javascript
返回 602 个结果(-
按预期工作)
cats stars:>10 +language:javascript
返回 112 个结果
我知道可以使用多个线程编译多个模块,其中每个线程编译一个模块,但是如果我有一个大模块怎么办?Javac 或 Eclipse Java Compiler 是否支持并行编译单个模块(使用多个线程)?或者有没有其他支持它的Java编译器?
更新:我创建了一个包含约 50k 个简单方法的 Java 源文件(仅用于此测试),例如:
static int add1(int a, int b, int c) {
return 2 * a + 55 * b - c;
}
static int add2(int a, int b, int c) {
return 2 * a + 55 * b - c;
}
static int add3(int a, int b, int c) {
return 2 * a + 55 * b - c;
}
Run Code Online (Sandbox Code Playgroud)
这些方法不相互依赖,因此编译可以并行完成(至少在理论上是这样)。Javac
在我的 12 核 + HT 机器上编译这个文件导致平均 …
我制作了一个 Java 代理,它在运行时连接到 JVM并检测所有加载的项目类并插入一些日志记录语句。总共有11k个班级。余测量由所花费的总时间transform
我的方法ClassFileTransformer
,它是3秒。但整个仪器过程的持续时间大约需要 30 秒。这就是我重新转换课程的方式:
instrumentation.retransformClasses(myClassesArray);
Run Code Online (Sandbox Code Playgroud)
我假设 JVM 占用了大部分时间来重新加载更改的类。那正确吗?如何加快检测过程?
更新:
当我的代理被附加时,
instrumentation.retransformClasses(myClassesArray);
Run Code Online (Sandbox Code Playgroud)
只调用一次。
然后MyTransfomer
class 检测类并测量检测的总持续时间:
instrumentation.addTransformer(new MyTransfomer(), true);
instrumentation.retransformClasses(retransformClassArray);
Run Code Online (Sandbox Code Playgroud)
在所有类都被检测(从初始数组)(全局缓存跟踪检测的类)之后total
,打印出来,大约需要 3 秒。但max-min
大约是 30 秒。
更新 2:
查看堆栈跟踪后,发生了以下情况:我调用
instrumentation.retransformClasses(retransformClassArray);
Run Code Online (Sandbox Code Playgroud)
它调用本机方法retransformClasses0()
。一段时间后(!)JVM 调用该类的transform()
方法sun.instrument.InstrumentationImpl
(但该方法一次只使用一个类,因此 JVM 连续多次调用该方法),它调用具有包含所有类的列表transform()
的sun.instrument.TransformerManager
对象ClassTransformers
注册并调用这些转换器中的每一个来转换类(我只注册了一个转换器!!)。
所以在我看来,大部分时间都花在 JVM 上(在retransformClasses0()
被调用之后和每次调用之前sun.instrument.InstrumentationImpl.transform()
)。有没有办法减少 JVM 执行此任务所需的时间?
我有自己的 JDI 调试器,它toString
在某些对象上调用该方法:
com.sun.jdi.ObjectReferenceobject object = ...
ThreadReference threadRef = frameProxy.threadProxy().getThreadReference();
Value value = object.invokeMethod(threadRef, toStringMethod,
Collections.EMPTY_LIST, ObjectReference.INVOKE_SINGLE_THREADED);
Run Code Online (Sandbox Code Playgroud)
问题是即使在 toString() 方法中没有设置断点, invokeMethod 也永远不会终止,所以我的调试器挂起。例如,当我在Double
对象上调用 this 时会发生这种情况。
如何invokeMethod
在一段时间后终止执行?
更新:我尝试实现我自己的Double
对象并System.out.println()
在方法的开头和结尾放置了一些语句,toString()
看起来该方法执行得很好,但由于某种原因调试器没有收到结果。也许这是 JDI 中的一个错误,因为有很多这样的错误,但我不是在为此寻找解决方案,我只是在寻找一种方法来中止执行,invokeMethod()
如果它花费太多时间。
更新 2:我尝试了ThierryB 的建议,但我只能frameProxy.threadProxy().stop(object);
在经理线程中调用。并且管理器线程被阻塞,invokeMethod()
因此它不会执行我的命令。我试过这样的事情:
boolean[] isFinished = new boolean[2];
isFinished[0] = false;
DebuggerManagerThreadImpl managerThread = debugProcess.getManagerThread();
new Thread(() - > {
try {
Thread.sleep(2000);
if (!isFinished[0]) {
System.out.println("Invoked"); …
Run Code Online (Sandbox Code Playgroud) 我想为 Java 创建一个反向调试器(一个可以在程序执行中倒退的调试器),为此我需要在程序执行的同时存储变量数据。我将为此使用全局缓存和更新缓存的静态方法。
我想以这样的方式检测加载的类,在每个字段/变量修改后,我的静态方法将被调用:例如:
public static void updateCache(String fullVarName, Object value){...}
Run Code Online (Sandbox Code Playgroud)
我观察到的是,当一个字段被更新时,putfield
就会执行一条指令。当局部变量被更新时,使用(I)STORE
指令。所以我想到了检测类,每当发现这样的操作码时,我只需插入另一个getfield
或ILOAD
之后,以获取更新的字段/变量的值,然后我使用 aninvokestatic
调用我的静态方法并提供所有必要的信息。
问题是,还有其他使用情况下,变量的集合或阵列以及它们与更新时,如特定的方法来更新HashMap
与map.put(key, value)
。所以我也需要拦截这些调用,但是有很多这样的方法,我需要找到所有这些方法并对其进行硬编码......
有解决方法吗?或者也许我遗漏了一些东西,有一个更简单的解决方案。
编辑:我之前也研究过 JVMTI 并运行了一些基准测试。对于我的用例来说,它似乎太慢了,例如给我的程序增加了 7-100 倍的减速.....
因此,JDI
允许我们在调试对象应用程序中设置断点,然后StackFrame
通过获取当前断点JDWP
。据我了解,JVMTI
用于在调试者端将请求的信息发送到JDI
through JDWP
。
是否有可能从被调试者本身获取电流StackFrame
(因此无需将其发送到调试器......被调试者将是它自己的调试器)?
例如考虑以下代码:
//client code
int a = 5;
StackFrame frame = ...
//list will contain variable "a"
List<LocalVariable> visibleVariables = frame.visibleVariables();
Run Code Online (Sandbox Code Playgroud) 这就是我想要实现的:如果有一个方法a()
调用 method b()
,我想知道谁调用了 method b()
。
public void a(){
b();//but it is not necessarily in the same class
}
public void b(){
String method = getCallerMethod();//returns 'a'
}
Run Code Online (Sandbox Code Playgroud)
现在,这可以在 Java 9+ 中使用 API 高效地实现StackWalker
。在 Java 8 中,我可以使用Thread.currentThread().getStackTrace()
or new Exception().getStackTrace()
,但这两种方法都非常慢。我不需要整个堆栈跟踪,我只需要堆栈跟踪中的前一帧,并且只需要该帧中的方法名称(可能还有类名称)。
有没有办法在 Java 8 中有效地实现这一点?
DCEVM 如何给 JVM 打补丁,使其既可以在正常模式下也可以在XXaltjvm
模式下启动?它对普通人有libjvm.so/jvm.dll/libjvm.dylib
什么作用?
所以Java的调试接口是使用JVMTI作为后端的....但是JVMTI需要在目标架构上编译,那么这些JDI使用的JVMTI函数是不是预先编译好并作为库随JDK一起提供的呢?这意味着我可以在不使用 JDI 的情况下使用那些预编译库……是吗?我假设只有少数函数已经编译,但如果我需要这些函数,那么我不需要自己编译它们的麻烦......
我使用过这样的东西:
struct Node
{
char name[50];
Node *left,*right;
};
int main()
{
char cmd[10];
Node* p=NULL;
scanf("%s",&cmd);
if (p == NULL)
{
// do something
// THIS NEVER GETS EXECUTED
// WHYYYYY????
//THIS IS STRANGE
}
}
Run Code Online (Sandbox Code Playgroud)
所以基本上,p
在我读入cmd
变量后,指针会改变它的值.我试图注释掉scanf
代码,然后一切正常.很奇怪.
根据OpenJDK 的网站,可以将线程附加到 Hotspot(动态附加 API),该线程可以收集有关它的信息。我在互联网上找不到任何关于如何获取有关 Hotspot 内部数据结构的信息,例如操作数堆栈或字节码解释器的状态(以了解当前正在执行哪个字节码)或检索当前堆栈帧等的材料。
另外,如果动态连接 API 无法实现这一点,那么如何使用可服务性代理来完成此操作?我在互联网上找到的唯一示例是来自 Github 的要点,它展示了如何附加到正在运行的 JVM 并获取某些字段的值。那么如何访问JVM中的上述内部数据结构呢?
java ×9
debugging ×4
jvmti ×4
jdi ×3
jvm ×3
breakpoints ×2
jvm-hotspot ×2
performance ×2
bytecode ×1
c ×1
c++ ×1
compilation ×1
dcevm ×1
exception ×1
github-api ×1
hotswap ×1
hotswapagent ×1
javaagents ×1
javac ×1
pointers ×1
stack-frame ×1
throwable ×1