-
-
Notifications
You must be signed in to change notification settings - Fork 807
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow extracting line number from advice #741
Comments
I see this with the 1.10.1 milestone. Was it actually implemented? If so is there any docs on how to use it? If not is there any immediate plans for it? |
Sorry for the confusion, I use the field as "reported version" and close the issue once fixed. I did not yet have time for it, unfortunately. Was doing a lot of Mockito stuff in the last weeks but I will certainly look into it at some point! |
Something like this is what I had in mind...
But I'm curious to see how you decide to implement it. |
I have looked into this, thinking it's a minor change but it turns out this would require some reorganization The way It can still be done by:
I'm still planning to add this, it's just not as trivial as I hoped. |
Thanks for the update! Sad that it's not straightforward. |
I made some progress already, it's mainly due to the JVM not treating it as real metadata but it's overcomeable, I'm sure. |
Just to let you know, I am a bit stuck on this despite looking into it for quite a while. The problem is that the line number is not known when the enter advice is dispatched. In the general (but unlikely case), it might not even be known in the exit advice. I do however have a prototype that you can plug yourself. I will continue thinking about this issue, maybe there is a way to get this done properly. public class Sample {
public static void main(String[] args) throws Exception {
Advice advice = Advice.withCustomMapping()
.bind(LineNumber.class, new StackManipulation() {
@Override
public boolean isValid() {
return true;
}
@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
Integer line = LineExtractingMethodVisitor.LINE.get();
methodVisitor.visitLdcInsn(line == null ? -1 : line);
return new Size(1, 1);
}
}, int.class)
.to(Sample.class);
Class<?> type = new ByteBuddy()
.redefine(Sample.class)
.name("linenumber.Sample")
.visit(new AsmVisitorWrapper.ForDeclaredMethods().method(named("bar"), new LineExtractingMethodVisitorWrapper()))
.visit(advice.on(named("bar")))
.make()
.load(Sample.class.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
Object instance = type.getConstructor().newInstance();
type.getMethod("bar").invoke(instance);
}
public void bar() {
System.out.println("In the method");
}
@Retention(RetentionPolicy.RUNTIME)
public @interface LineNumber { }
@Advice.OnMethodEnter
@Advice.OnMethodExit
public static void enter(@LineNumber int lineNumber) {
System.out.println(lineNumber);
}
public static class LineExtractingMethodVisitorWrapper implements AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper {
@Override
public MethodVisitor wrap(
TypeDescription instrumentedType,
MethodDescription instrumentedMethod,
MethodVisitor methodVisitor,
Implementation.Context implementationContext,
TypePool typePool,
int writerFlags,
int readerFlags
) {
return new LineExtractingMethodVisitor(methodVisitor);
}
}
public static class LineExtractingMethodVisitor extends MethodVisitor {
static final ThreadLocal<Integer> LINE = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return -1;
}
};
public LineExtractingMethodVisitor(MethodVisitor methodVisitor) {
super(Opcodes.ASM9, methodVisitor);
}
@Override
public void visitLineNumber(int line, Label start) {
LINE.set(line);
super.visitLineNumber(line, start);
}
@Override
public void visitEnd() {
super.visitEnd();
LINE.remove();
}
}
} |
Thanks for the update! |
Is there a major version of this feature? |
You can use the code above but there is no plan for this feature right now. |
You can use an Executable rather then a Method type if you also want to process constructors (which cannot be represented as Method). |
I understand the problem, I set all the function buried points by default, just remove the constructor, thank you very much |
If possible, allow accessing the line number from advice.
The text was updated successfully, but these errors were encountered: