我正在使用ASM Java库来替换一些反射.我生成了这个方法的主体:
void set(Object object, int fieldIndex, Object value);
Run Code Online (Sandbox Code Playgroud)
使用此生成的方法,我可以在运行时在不使用反射的情况下在对象上设置字段.它很棒.但是,我发现原始字段失败了.这是我的set方法的相关部分:
for (int i = 0, n = cachedFields.length; i < n; i++) {
mv.visitLabel(labels[i]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, targetClassName);
mv.visitVarInsn(ALOAD, 3);
Field field = cachedFields[i].field;
Type fieldType = Type.getType(field.getType());
mv.visitFieldInsn(PUTFIELD, targetClassName, field.getName(), fieldType.getDescriptor());
mv.visitInsn(RETURN);
}
Run Code Online (Sandbox Code Playgroud)
此代码为选择生成案例标签.它适用于对象,但对于原语,我收到此错误:
期待在堆栈上找到浮动
好的,这是有道理的,我需要自己进行拆箱.我实现了以下内容:
for (int i = 0, n = cachedFields.length; i < n; i++) {
mv.visitLabel(labels[i]);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, targetClassName);
mv.visitVarInsn(ALOAD, 3);
Field field = …Run Code Online (Sandbox Code Playgroud) 我工作的人注意到(在堆栈跟踪中)当使用-javaagent运行jvm时:spring-instrumentation.jar我的JAXB注释类中有奇怪的新方法,我们没有编写它们:例如SomeJaxbAnnotatedClass $ JaxbAccessorM_getFields_setFields_java_util_Set.get
这是否意味着jaxb在可用时使用字节码检测?我在哪里可以阅读有关此功能的更多信息
谢谢,Yuval
我正在研究计算StackFrameMap(SFM)中条目的代码.目标是能够生成(SFM)条目,使Java 7字节码验证器满意.遵循TDD方法,我开始为验证者创建伪造的SMF条目以进行投诉; 我会用我正确计算的条目替换它们,看看我是否正确地做了.
问题是:我不能让字节码验证器抱怨.这是一个示例,从原始Java代码开始(此代码不应该做任何有用的事情):
public int stackFrameTest(int x) {
if (x > 0) {
System.out.println("positive x");
}
return -x;
}
Run Code Online (Sandbox Code Playgroud)
这会生成以下字节码(使用SFM):
public int stackFrameTest(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: ifle 12
4: getstatic #47 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #85 // String positive x
9: invokevirtual #55 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: iload_1
13: ineg
14: ireturn
StackMapTable: number_of_entries = 1
frame_type = 12 /* same */
Run Code Online (Sandbox Code Playgroud)
现在,我将SFM更改为包含以下内容:
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame …Run Code Online (Sandbox Code Playgroud) 我的项目中有很多值对象.
我正在使用项目lombok来消除一些样板,所以我的值对象看起来像下面这样:
@Value
@Accessors(fluent = true)
public class ValueObject {
private final String firstProp;
private final int secondProp;
}
Run Code Online (Sandbox Code Playgroud)
不错,几乎没有样板.
现在,我在测试中经常使用all-args构造函数.它看起来很乱,所以我想我会介绍Builder Pattern变种:
public class ValueObjectBuilder {
private static final int DEFAULT_VALUE_FOR_SECOND_PROP = 666;
private String firstProp = "default value for first prop;
private int secondProp = DEFAULT_VALUE_FOR_SECOND_PROP;
private ValueObjectBuilder() {}
public static ValueObjectBuilder newValueObject() {
return new ValueObjectBuilder();
}
public ValueObjectBuilder withFirstProp(String firstProp) {
this.firstProp = firstProp
return this;
}
public ValueObjectBuilder withFirstProp(int secondProp) {
this.secondProp = secondProp;
return this; …Run Code Online (Sandbox Code Playgroud) 我正在使用ASM进行在线字节码方法内联优化.我的更改基于示例3.2.6 Inline Method(http://asm.ow2.org/current/asm-transformations.pdf).测试示例(在Caller :: test中内联被调用者的计算(int,int))是:
public class Caller {
final Callee _callee;
public Caller(Callee callee){
_callee = callee;
}
public static void main(String[] args) {
new Caller(new Callee("xu", "shijie")).test(5, 100);
}
public void test(int a, int b){
int t = a;
int p = b;
int r = t+p-_callee.calculate(a, b);
int m = t-p;
System.out.println(t);
}
}
public class Callee {
final String _a;
final String _b;
public Callee(String a, String b){
_a = a;
_b …Run Code Online (Sandbox Code Playgroud) java bytecode inline bytecode-manipulation java-bytecode-asm
我有两个示例类文件,一个来自示例Java应用程序,另一个来自示例C app(使用LLJVM编译为字节码).
看看他们的输出,我可以通过javap -c -p看到,为了初始化(静态)字段,Java应用程序显示以下块:
static {};
Code:
0: sipush 1339
3: putstatic #7 //Field SRV_ID
etc
Run Code Online (Sandbox Code Playgroud)
<clinit>如果我理解的话,基本上就是这个方法.或者由我正在使用的VM检测到.
然而,C-app有这个:
public {};
Code:
0: sipush 1339
3: putstatic #7 //Field SRV_ID
etc
Run Code Online (Sandbox Code Playgroud)
这是什么?我的VM没有检测到它.
示例类文件.第一个来自Java应用程序打印消息并等待20秒,重复.第二个是大致相同的C应用程序.
http://www.fast-files.com/getfile.aspx?file=156962
http://www.fast-files.com/getfile.aspx?file=156961
这样做的道歉 - 我不会立即知道如何附加文件或有效地显示.class文件.
假设我有以下代码片段:
@RequestMapping(method = RequestMethod.GET)
public List<Article> getArticles(@RequestParam int offset,
@RequestParam int limit) {
...
}
Run Code Online (Sandbox Code Playgroud)
当参数名称未明确声明为注释参数时,Spring如何将HTTP查询参数与正确的形式参数匹配?
它是否假设形式参数名称始终存在于字节码中?
据我了解,并非总是如此.只有在以下情况下才能从字节码中检索形式参数名称:
a)类文件已使用-parameters javac选项编译
b)类文件已使用-g(或-g:vars)javac选项进行编译,该选项添加包含真实变量名称的调试信息(因为形式参数存储为方法的第一个局部变量)
这可能是一个愚蠢的问题,但是,考虑到输出,比如..
>>> from dis import dis
>>> def myfunc(x):
... print x ** 2
...
>>> dis(myfunc)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (2)
6 BINARY_POWER
7 PRINT_ITEM
8 PRINT_NEWLINE
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
..或.pyc文件 - 是否可以将其重新组合成一个有效的Python源代码?即在哪里reassemble(dis(myfunc)) == "def reassembled_function(x):\n print x ** 2"
不是出于任何特殊的实际原因,我只是好奇这是否可能,或者是否已经尝试过......
字节码操作的合法用途是什么以及人们如何在实践中实现基于字节码操作的解决方案?
更新:我应该更清楚地说明这个问题实际上是关于人们使用什么模式和技术来使代码在字节码操作的帮助下飞行.
像已经提到的面向方面编程或动态构建代理对象和类似技术的东西.
用法示例:
我想在类字段上添加一个自定义注释@MyContainer,然后在所有这些字段上自动添加相关的Hibernate注释(取决于字段类型和属性).
另外,我需要将JAXB XmlType注释添加到类中,并将类型名称基于类名.
我还希望基于其类型等向字段添加注释.所有添加的注释应该在运行时可用(因此hibernate/JAXB可以找到它们).
我知道以下选项:
我的主要目标是:
如果已经完成此类工作的人能够为这样的任务推荐最佳方法(也许还有潜在的陷阱),我将不胜感激.
java compiler-construction annotations bytecode-manipulation
java ×9
bytecode ×7
annotations ×1
boilerplate ×1
builder ×1
inline ×1
jaxb ×1
jvm ×1
jvm-bytecode ×1
lombok ×1
python ×1