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
Unable to transform AccessibleObject class #150
Comments
You actually delegate to the |
When I call I have tried:
|
There is a bug in the VM where classes on the bootstrap class path cannot be located as a class file due to some caching issue such that Byte Buddy (or any library) cannot locate it. You can work around this by resolving the jar file explicitly: TypePool typePool = TypePool.Default.of(new ClassFileLocator.Compound(
new ClassFileLocator.ForJarFile(new JarFile(file)),
ClassFileLocator.ForClassLoader.of(Main.class.getClassLoader()))); The file in this context is your reference to the jar added to the bootstrap class path. Note that you need to align your matcher accordingly .method(named("setAccessible").and(takesArguments(boolean.class))) to avoid instrumenting the internal implementation. |
By the way, after adfing a class to the bootratrap class path, you can simply refer to the loaded version, no need to use the type pool. |
Awesome. Using the loaded version is working now. I was still having an issue using the type pool as you had shown earlier. Thank you so much for your help. I'm running into some reflection problems now, so my ultimate goal still may not be possible, but I'm glad I was able to get the byte-buddy parts working with your help. Edit: Actually I think I should be good to go. I had forgotten how simple I had made my sample implementation. I believe I can get things working with my full implementation. |
Is it possible for me to use the |
Looks like I can use the Would it be possible in a future release to have a separate annotations module so that not all of byte-buddy needs to be included to use the annotations? If this is something you are open to, I could probably do a pull request. |
If you want to use annotations, I would recommend you to use the type pool again as suggested before. What is your problem with it? I had your example working with the suggestion above. |
I've got it working now with the type pool and with the If I can get more fine grained access check permissions working by interjecting custom Thanks for your help. |
You are welcome. Maybe, you would also be interested in using the Advice class for your purposes. It allows you to add code rather than replacing it. Also, since it is adding the code rather than delegating, you can skip the bootstrap injection. Let me know of any write-up! |
For the security checks I think it can only be done through interjection. My plan is to replace to the Unless Advice allows conditionally not continuing to the original implementation, I think I need to replace the whole method. |
Currently, Advice does not allow skipping the original code, even-though I consider adding this feature jn a future version. For invoking the setAccessible0 method, check out the MethodCall implementation. |
class SetAccessibleImplementation {
private static void setAccessible1(AccessibleObject ao, boolean flag){
}
} String setAccessible0MethodName = "setAccessible0";
Class[] paramTypes = new Class[2];
paramTypes[0] = AccessibleObject.class;
paramTypes[1] = boolean.class;
Method setAccessible0Method = AccessibleObject.class.getDeclaredMethod(setAccessible0MethodName, paramTypes);
// Previous code omitted
.type(named("com.leacox.example.bytebuddy.instrument.java.lang.reflect.SetAccessibleImplementation"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(
DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader) {
return builder.method(named("setAccessible1"))
.intercept(
MethodCall.invoke(new MethodDescription.ForLoadedMethod(setAccessible0Method)).withAllArguments());
}
}) |
Looking through a lot of the tests it looks like The Hopefully I'm just missing something about how you are thinking I should use |
I thought more about chaining the calls. I assume that you are throwing an exception in your real interceptor if the security check fails? In the case, the following would work: builder.method(named("setAccessible").and(takesArguments(boolean.class))) The That said, I am looking into adding a skip instruction to the |
Your assumption is correct; my interceptor implementation will throw a |
Well, the documentation does indeed not make this explicit but Byte Buddy generates standard Java code. If an exception is thrown, unless you do not explicitly catch the exception from an interceptor, the chained byte code is never reached. |
Got it. Thanks for all your help. |
No problem and thanks for the idea of creating a property to skip the original method. |
I was hoping to be able to use byte-buddy to transform the
setAccessible
method of theAccessibleObject
class to allow more fine grained access check permissions. Since theAccessibleObject
is a standard Java class I know this is likely a little bit of a stretch, but I was hoping it would be possible.It seems like I'm pretty close but I end up with a
class redefinition failed: attempted to change the schema
error. As far as I can tell I just have a class I'm delegating two with exactly one matching method, so I'm not sure why the JVM thinks I'm adding/removing a field.I've put my delegate class in a separate jar and use the instrumentation API to append it to the bootstrap classloader, and prior to doing that I would get ClassNotFoundExceptions, so I don't think this most recent error is a classpath issue.
I've put together a very small sample project where I'm trying to replace the
setAccessible
method with a new one that just prints a string to the console. If it's possible to get this sample project working, then I should be able to translate that into the more complicated permissions checks case.My sample project is at https://github.com/johnlcox/bytebuddy-accessibleobject
I guess my questions are, am I doing something wrong? Is this simply not possible with current JVMs? Could it possibly be a bug?
Below is the error stack trace I am getting:
The text was updated successfully, but these errors were encountered: