我有一个SomeObject.java文件:
class SomeObject {
String name;
}
Run Code Online (Sandbox Code Playgroud)
编译它会创建一个包含字节码的SomeObject.class文件.
0xCAFEBABE...
Run Code Online (Sandbox Code Playgroud)
如果我们在JVM上使用SomeObject,它将由当前的类加载器加载,并且一切正常.
现在让我们假设我想要一些动态代码生成.我可以写我的自定义注释
@Target(ElementType.TYPE)
public @interface Data {
...
}
Run Code Online (Sandbox Code Playgroud)
并将其作为修饰符添加到类声明中:
@Data
class SomeObject {
String name;
}
Run Code Online (Sandbox Code Playgroud)
我也可以在运行时保留它@Retention(RetentionPolicy.RUNTIME):
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Data {
...
}
Run Code Online (Sandbox Code Playgroud)
用于字节码注入的注释在哪里?在使用适当的运行时保留注释加载类时,类加载器是否会注入字节码,如下图所示:
source -(compile)-> bytecode -(classloader bytecode injection)-> injected bytecode -(classloading)-> JVM loaded bytecode
Run Code Online (Sandbox Code Playgroud) 我正在玩javap和一些非常简单的代码,这引发了一个 - 希望很简单 - 的问题.
这是代码优先:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(m1());
System.out.println(m2());
}
private static String m1() {
return new String("foobar");
}
private static String m2() {
String str = "foobar";
return new String(str);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我编译了代码并查看了输出(现在省略-verbose).
$ javap -c Main.class
Compiled from "Main.java"
public class Main {
public Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: getstatic #2 // …Run Code Online (Sandbox Code Playgroud) 在检查函数的R代码时,它列出了一个字节码(例如,对于glm):. 我到处寻找一个简单的解释,实际上是"0x7f8f3c954540".我知道字节码是什么,但我假设"0x7f8f3c954540"实际上并不是glm函数整个代码的高度压缩机器可处理版本.它是CRC,它在内存中的位置的链接,还是前几位?
我正在尝试打印一个数字,但我收到错误,说我的打印功能错误:
define i32 @main() {
entry:
%d = shl i32 2, 3
%call = call i32 (i8*, ...)* @printf(i8* %d)
ret i32 1
}
declare i32 @printf(i8*, ...)
Run Code Online (Sandbox Code Playgroud)
这是错误:
Error in compilation: /bin/this.program: llvm.ll:4:44: error: '%d' defined with type 'i8'
%call = call i32 (i8*, ...)* @printf(i8* %d)
^
Run Code Online (Sandbox Code Playgroud)
还有其他一些打印功能可以解决这个问题吗?
想象一下这个简单的函数创建一个变量的修改值default,modified:
default = 0
def modify():
modified = default + 1
print(modified) # replace with OS call, I can't see the output
modify() # 1
default # 0
Run Code Online (Sandbox Code Playgroud)
拆解:
import dis
dis.dis(modify)
2 0 LOAD_GLOBAL 0 (default)
3 LOAD_CONST 1 (1)
6 BINARY_ADD
7 STORE_FAST 0 (modified)
3 10 LOAD_GLOBAL 1 (print)
13 LOAD_FAST 0 (modified)
16 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
19 POP_TOP
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
我不能改变这个功能modify(),但我知道它的内容是直接(我可以看到代码)还是间接(反汇编).我需要它是获取modified …
尝试对服务器应用程序启动进行故障排除时,我在旧版Java字节码中发现以下构造。我的IDE反编译了一些第三方库,我很好奇它的有效性-从来没有见过关键字 可以用作字节码中的字段名称。
字节码版本为48.0(Java 1.4)。
public final class f implements UserContext{
private final String try;
private final UserInfo do;
// a lot of code here
public UserInfo getUserInfo(){
return this.do;
}
public String getViewName(){
return this.try;
}
}
Run Code Online (Sandbox Code Playgroud)
好像该库是使用一些混淆功能进行编译的,但是如何在JVM级别上呢?是否允许在JVM启动时没有特殊标志?
更新:该UserInfo字段的正确getter名称是getUserInfo-很抱歉使每个人都对具有不同返回值的方法的模棱两可的命名感到困惑,这是一个复制粘贴问题,因为代码位于没有直接访问该站点的远程计算机上。
我有一个类似的界面:
public interface Getter {
Object get(Params params);
}
Run Code Online (Sandbox Code Playgroud)
我使用对不同方法的反射调用来实现:
public class GetterImpl implements Getter {
private final Object target;
private final Method method; //doStuff method
public GetterImpl(Object target, Method method) {
this.target = target;
this.method = method;
}
@Override
public Object get(Params params) {
//both the target and arguments depend on Params
return method.invoke(chooseTarget(params), prepareArgs(params));
}
private Object chooseTarget(Params params) {
if (params.getTargetOverride() != null) {
return params.getTargetOverride();
}
return target;
}
private Object[] prepareArgs(Params params) {
...
} …Run Code Online (Sandbox Code Playgroud) 在堆中移动对象时,JVM 可以轻松更新局部变量、静态引用、类实例或对象数组实例的引用。但是它如何更新推送到操作数堆栈的引用呢?
你好。
我想找到方法调用开始和结束之间的指令范围。
我不想简单地更改方法调用所有者/名称/描述。
有了预期的结果,我希望能够做到:
我一直在尝试不同的技术来实现这一目标:
start和end
我会给你一些我想要什么的例子,以防这里有任何混淆。
首先,看看我下面的测试代码,然后回到这里。
我希望找到/删除整个方法调用anotherMethod4并将其替换为一个简单的true,从而生成以下代码:
System.out.println(
anotherMethod1(
anotherMethod2("a", "b") ?
"c" : anotherMethod3("d", "e") ? "f" : "g",
true ? "j" : "k"
) ? "l" : "m"
);
Run Code Online (Sandbox Code Playgroud)
我希望找到/删除整个方法调用anotherMethod1并将其替换为一个简单的false,从而生成以下代码:
System.out.println(
false ? "l" : "m"
);
Run Code Online (Sandbox Code Playgroud)
我希望删除对 的整个方法调用System.out.println,从而生成以下代码:
private Main()
{
}
Run Code Online (Sandbox Code Playgroud)
这一定是可能的吗?
这是我当前的测试代码:
private Main()
{
System.out.println(
anotherMethod1(
anotherMethod2("a", …Run Code Online (Sandbox Code Playgroud) bytecode ×10
java ×4
jvm ×3
function ×2
annotations ×1
assembly ×1
byte-buddy ×1
classloader ×1
disassembly ×1
if-statement ×1
javap ×1
jvm-bytecode ×1
llvm ×1
python ×1
r ×1
while-loop ×1