I started learning Java Agent few days ago. But documentation is not very good and beginners like me struggling to understand the basics. I created a basic multiplier class and export it to runnable jar using eclipse. Here is the code snippet.
Main jar file:
public class Multiplier {
public static void main(String[] args) {
int x = 10;
int y = 25;
int z = x * y;
System.out.println("Multiply of x*y = " + z);
}
}
Bytecode for above class
Now I want to manipulate the value of x from an agent. I tried to create the Agent class like this
Agent:
package myagent;
import org.objectweb.asm.*;
import java.lang.instrument.*;
public class Agent {
public static void premain(final String agentArg, final Instrumentation inst) {
System.out.println("Agent Started");
int x_modified = 5;
//Now How to push the new value (x_modified) to the multiplier class?
//I know I have to use ASM but can't figure it out how to do it.
//Result should be 125
}
}
My Question
How do I set the value of x from agent class to multiplier class using ASM?
Result should be 125.
The first thing, your agent has to do, is registering a ClassFileTransformer. The first thing, the class file transformer should do in its transform method, is checking the arguments to find out whether the current request is about the class we’re interested in, to return immediately if not.
If we are at the class we want to transform, we have to process the incoming class file bytes to return a new byte array. You can use ASM’s ClassReader to process to incoming bytes and chain it to a ClassWriter to produce a new array:
import java.lang.instrument.*;
import java.security.ProtectionDomain;
import org.objectweb.asm.*;
public class ExampleAgent implements ClassFileTransformer {
private static final String TRANSFORM_CLASS = "Multiplier";
private static final String TRANSFORM_METHOD_NAME = "main";
private static final String TRANSFORM_METHOD_DESC = "([Ljava/lang/String;)V";
public static void premain(String arg, Instrumentation instrumentation) {
instrumentation.addTransformer(new ExampleAgent());
}
public byte[] transform(ClassLoader loader, String className, Class<?> cl,
ProtectionDomain pd, byte[] classfileBuffer) {
if(!TRANSFORM_CLASS.equals(className)) return null;
ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(cr, 0);
cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
#Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(
access, name, desc, signature, exceptions);
if(name.equals(TRANSFORM_METHOD_NAME)
&& desc.equals(TRANSFORM_METHOD_DESC)) {
return new MethodVisitor(Opcodes.ASM5, mv) {
#Override
public void visitIntInsn(int opcode, int operand) {
if(opcode == Opcodes.BIPUSH && operand == 10) operand = 5;
super.visitIntInsn(opcode, operand);
}
};
}
return mv;
}
}, 0);
return cw.toByteArray();
}
}
Note that by passing the ClassWriter to our custom ClassVisitor’s constructor and passing the MethodVisitor returned by the super.visitMethod invocation to our MethodVisitor’s constructor, we enable a chaining that reproduces the original class by default; all methods we’re not overriding will delegate to the specified ClassWriter/MethodVisitor reproducing the encountered artifact. Compare with the tutorial about ASM’s event model.
The example above enables an optimization by also passing the ClassReader instance to the ClassWriter’s constructor. This improves the efficiency of instrumenting a class when only making small changes, like we do here.
The crucial part is overriding visitMethod to return our custom MethodVisitor when we are at the “hot” method and overriding visitIntInsn to change the desired instruction. Note how these methods delegate to the super calls when not altering the behavior, just like the methods we didn’t override.
You have declared x inside main method. So it's scope is local. That's why you can't change the value of x from any other class.
To use ASM you need a custom CodeWriter in a custom ClassWriter which you pass to a ClassReader. http://asm.ow2.org/doc/tutorial.html This will allow you to visit all instructions in the code for each method.
In particular you will need to override the visitIntInsn method so when you see the first BIPUSH instruction in main you can replace the value 10, with what ever value you chose.
The output of ClassWriter is a byte[] which your Instrumentation will return instead of the original code at which point x will be whatever value you made it in the code.
Related
I want to gain reflective access to java.lang.String's package private constructor.
Namely, this one:
/*
* Package private constructor which shares value array for speed.
* this constructor is always expected to be called with share==true.
* a separate constructor is needed because we already have a public
* String(char[]) constructor that makes a copy of the given char[].
*/
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}
Creating a MethodHandle for it is simple enough, and so is invoking it.
The same is true for using Reflection directly.
But I'm curious whether it's possible to directly call the constructor via functional interfaces.
27602758 touches on a somewhat similar issue, but the solutions provided do not appear to work in this case.
The test case below compiles without issues. Everything works, except for the actual interface invocation.
package test;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
public class Test {
// Creates a new String that shares the supplied char[]
private static interface StringCreator {
public String create(char[] value, boolean shared);
}
// Creates a new conventional String
private static String create(char[] value, boolean shared) {
return String.valueOf(value);
}
public static void main(String[] args) throws Throwable {
// Reflectively generate a TRUSTED Lookup for the calling class
Lookup caller = MethodHandles.lookup();
Field modes = Lookup.class.getDeclaredField("allowedModes");
modes.setAccessible(true);
modes.setInt(caller, -1); // -1 == Lookup.TRUSTED
// create handle for #create()
MethodHandle conventional = caller.findStatic(
Test.class, "create", MethodType.methodType(String.class, char[].class, boolean.class)
);
StringCreator normal = getStringCreator(caller, conventional);
System.out.println(
normal.create("foo".toCharArray(), true)
// prints "foo"
);
// create handle for shared String constructor
MethodHandle constructor = caller.findConstructor(
String.class, MethodType.methodType(void.class, char[].class, boolean.class)
);
// test directly if the construcor is correctly accessed
char[] chars = "foo".toCharArray();
String s = (String) constructor.invokeExact(chars, true);
chars[0] = 'b'; // modify array contents
chars[1] = 'a';
chars[2] = 'r';
System.out.println(
s
// prints "bar"
);
// generate interface for constructor
StringCreator shared = getStringCreator(caller, constructor);
System.out.println(
shared.create("foo".toCharArray(), true)
// throws error
);
}
// returns a StringCreator instance
private static StringCreator getStringCreator(Lookup caller, MethodHandle handle) throws Throwable {
CallSite callSite = LambdaMetafactory.metafactory(
caller,
"create",
MethodType.methodType(StringCreator.class),
handle.type(),
handle,
handle.type()
);
return (StringCreator) callSite.getTarget().invokeExact();
}
}
Specficially the instruction
shared.create("foo".toCharArray(), true)
throws the following error:
Exception in thread "main" java.lang.IllegalAccessError: tried to access method java.lang.String.<init>([CZ)V from class test.Test$$Lambda$2/989110044 at test.Test.main(Test.java:59)
Why is this error still being thrown, despite access ostensibly being granted?
Can anyone come up with an explanation for why the generated interface has no access to a method that all of its components have access to?
Is there a solution or a viable alternative that actually works for this particular use case, without reverting to pure Reflection or MethodHandles?
Because I'm stumped.
The problem is that you override the lookup object to be trusted, so its access to a private method of String will pass the lookup procedure and lambda meta factory, but its still bound to your Test class as that’s the class which created the lookup object via MethodHandles.lookup() and the generated class will live in the same context. The JVM is quite generous regarding accessibility when it comes to these generated classes but apparently, accessing a private member of the bootstrap class java.lang.String from a class living in the context of your application class is not accepted.
You can get a lookup object living in an appropriate context via, e.g. MethodHandles.lookup() .in(String.class) (and then patching it to have private or “trusted” access), but then, you will get another problem: a class living in the context of java.lang.String (or just in the bootstrap loader’s context) will not have access to your custom interface StringCreator and can’t implement it.
The only solution is to use a lookup object living in the context of String and implementing one of the existing generic interfaces, accessible from the bootstrap class loader:
import java.lang.invoke.*;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field;
import java.util.function.BiFunction;
public class Test {
public static void main(String[] args) throws Throwable {
// Reflectively generate a TRUSTED Lookup for the String class
Lookup caller = MethodHandles.lookup().in(String.class);
Field modes = Lookup.class.getDeclaredField("allowedModes");
modes.setAccessible(true);
modes.setInt(caller, -1); // -1 == Lookup.TRUSTED
// create handle for shared String constructor
MethodHandle constructor = caller.findConstructor(
String.class, MethodType.methodType(void.class, char[].class, boolean.class)
);
// generate interface implementation for constructor
BiFunction<char[],Boolean,String> shared=getStringCreator(caller, constructor);
// test if the construcor is correctly accessed
char[] chars = "foo".toCharArray();
String s = shared.apply(chars, true);
chars[0] = 'b'; chars[1] = 'a'; chars[2] = 'r';// modify array contents
System.out.println(s); // prints "bar"
chars[0] = '1'; chars[1] = '2'; chars[2] = '3';
System.out.println(s); // prints "123"
}
private static BiFunction<char[],Boolean,String> getStringCreator(
Lookup caller, MethodHandle handle) throws Throwable {
CallSite callSite = LambdaMetafactory.metafactory(
caller,
"apply",
MethodType.methodType(BiFunction.class),
handle.type().generic(),
handle,
handle.type()
);
return (BiFunction) callSite.getTarget().invokeExact();
}
}
In a child class GreenSlime Im given a constructor with only three parameters (I cannot add any other instance variables). But the code keeps giving error about this line:super(loc,map,log); which I understand that the constructor should have the same amount of parameters. But my specs say that via the parent constructor, sets all fields. fullcharge must always be 4, and the starting value for charge is 0. I do know that I'm passing only 3 parameters instead of 5, but that's the instructions of my project say so. What am I doing wrong and what's the best approach/solution?
import java.io.PrintStream;
public class GreenSlime extends Threat {
public GreenSlime(Coord loc, Map map, PrintStream log)
{
super(loc,map,log);
super.fullCharge = 4;
super.charge = 0;
}
}
import java.io.PrintStream;
public abstract class Threat extends Thing {
protected int charge;
protected final int fullCharge;
public Threat(Coord c, String repr, int fullCharge, Map map, PrintStream log)
{
super(c,repr,map,log);
this.fullCharge = fullCharge;
charge = 0;
}
public abstract void spawn(Coord c);
#Override
public void doAction()
{
while(charge != fullCharge)
{
System.out.println("\"+repr()"+"#"+"getLoc()\" speading");
if(this.canPassThrough())
{
spawn(getPrevLoc().step(Direction.N));
spawn(getPrevLoc().step(Direction.S));
spawn(getPrevLoc().step(Direction.E));
spawn(getPrevLoc().step(Direction.W));
}
charge++;
}
}
}
public GreenSlime(Coord loc, Map map, PrintStream log)
{
super(loc,"",4,map,log);
}
I've supplied an empty string "" for repr, but you may need null or some other value.
In your code, the Threat constructor has a signature that accepts 5 arguments, but where as you're trying to pass only 3 arguments to it.
For my programming class in first year engineering I have to make a D-game in Java, with only very little knowledge of Java.
In one class I am generating a random integer via
public int rbug = (int)(Math.random() * 18);
every so many ticks. I have to use this integer in another class (in the requirements for an if-loop), and apparently it needs to be static. But when I change the variable to public int static, the value doesn't change any more.
Is there an easy way to solve this problem?
Edit: part of code added:
public int rbug = (int)(Math.random() * 18);
which is used in
public void render(Graphics g){
g.drawImage(bugs.get(rbug), (int)x, (int)y, null);
And in another class:
if(Physics.Collision(this, game.eb, i, BadBug.rbug)){
}
As error for BadBug.rbug I get the message
Cannot make a static reference to a non-static field
Using static to make things easier to access is not a very good ideal for design. You would want to make variables have a "getter" to access them from another class' instance, and possibly even a "setter". An example of this:
public class Test {
String sample = 1337;
public Test(int value) {
this.sample = value;
}
public Test(){}
public int getSample() {
return this.sample;
}
public void setSample(int setter) {
this.sample = setter;
}
}
An example of how these are used:
Test example = new Test();
System.out.println(example.getSample()); // Prints: 1337
example = new Test(-1);
System.out.println(example.getSample()); // Prints: -1
example.setSample(12345);
System.out.println(example.getSample()); // Prints: 12345
Now you might be thinking "How do I get a string from the class that made the instance variable within the class?". That's simple as well, when you construct a class, you can pass a value of the class instance itself to the constructor of the class:
public class Project {
private TestTwo example;
public void onEnable() {
this.example = new TestTwo(this);
this.example.printFromProject();
}
public int getSample() {
return 1337;
}
}
public class TestTwo {
private final Project project;
public TestTwo(Project project) {
this.project = project;
}
public void printFromProject() {
System.out.println(this.project.getSample());
}
}
This allows you to keep single instances of classes by passing around your main class instance.
To answer the question about the "static accessor", that can also be done like this:
public class Test {
public static int someGlobal = /* default value */;
}
Which allows setting and getting values through Test.someGlobal. Note however that I would still say that this is a horrible practice.
Do you want to get a new number every time that you want BadBug.rbug? Then convert it from a variable to a method.
I implemented a ClassFileTransformer for a javaagent using ASM. Because it has some bugs, I want to write a JUnit test case for it. How do I do this?
Using pseudo-code I thought along the lines:
// Have a test class as subject
public static class Subject {
public void doSomething(){...}
}
// Manually load and transform the subject
...?
// Normally execute some now transformed methods of the subject
new Subject().doSomething();
// Check the result of the call (i.e. whether the correct attached methods were called)
Assert.assertTrue(MyClassFileTransformer.wasCalled());
Now the question is: How do I manually load and transform the subject and make the JVM/Classloader use my manipulated version of it? Or do I completely miss something?
I got it. One needs to implement an own ClassLoader that does the same transformation with the test subject as the ClassFileTransformer (e.g. calls it). And of course the subject class may not already be loaded, so there may not be any direct usage of it. So I used Java reflection API to execute the methods of the subject class.
In a separate file:
public static class Subject {
public void doSomething(){...}
}
In the test:
private static class TransformingClassLoader extends ClassLoader {
private final String className;
public TransformingClassLoader(String className) {
super();
this.className = className;
}
#Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.equals(className)) {
byte[] byteBuffer = instrumentByteCode(fullyQualifiedSubjectClass);
return defineClass(className, byteBuffer, 0, byteBuffer.length);
}
return super.loadClass(name);
}
}
#Test
public void testSubject(){
ClassLoader classLoader = new TransformingClassLoader(fullyQualifiedSubjectClass);
Class<?> subjectClass = classLoader.loadClass(fullyQualifiedSubjectClass);
Constructor<?> constructor = subjectClass.getConstructor();
Object subject = constructor.newInstance();
Method doSomething = subjectClass.getMethod("doSomething");
doSomething.invoke(subject);
Assert.assertTrue(MyClassFileTransformer.wasCalled());
}
I would like some help on this matter,
Example:
public class A {
private void foo() {
//Who invoked me?
}
}
public class B extends A {}
public class C extends A {}
public class D {
C.foo();
}
This is basically the scenario. My question is how can method foo() know who is calling it?
EDIT: Basically I am trying to do a database Layer, and in class A I will create a method that will generate SQL statements. Such statements are dynamically generated by getting the values of all the public properties of the calling class.
Easiest way is the following:
String className = new Exception().getStackTrace()[1].getClassName();
But in real there should be no need for this, unless for some logging purposes, because this is a fairly expensive task. What is it, the problem for which you think that this is the solution? We may come up with -much- better suggestions.
Edit: you commented as follows:
basically i'am trying to do a database Layer, and in Class A i will create a method that will generate sql statements, such statements are dynamically generated by getting the values of all the public properties of the calling class.
I then highly recommend to look for an existing ORM library, such as Hibernate, iBatis or any JPA implementation to your taste.
Java 9: Stack Walking API
JEP 259 provides an efficient standard API for stack walking that allows easy filtering of, and lazy access to, the information in stack traces. First off, you should obtain an instance of StackWalker:
import static java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE;
// other imports
StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
After that you can call the getCallerClass() method:
Class<?> callerClass = walker.getCallerClass();
Regardless of how you configured the StackWalker instance, the getCallerClass method will ignore the reflection frames, hidden frames and those are related to MethodHandles. Also, this method shouldn't be called on the first stack frame.
Perhaps for your use case it would make sense to pass the class of the caller into the method, like:
public class A { public void foo(Class<?> c) { ... } }
And call it something like this:
public class B { new A().foo(getClass() /* or: B.class */ ); }
foo() is private, so the caller will always be in class A.
if you using slf4j as your application logging system.
you can using:
Class<?> source = org.slf4j.helpers.Util.getCallingClass();
I think it's faster than new Exception().getStackTrace(), since getStackTrace() alaways doing clone stacktrace.
I would use StackWalker
private static Class<?> getCallingClass(int skip) {
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
Optional<? extends Class<?>> caller = walker.walk(frames ->
frames.skip(skip).findFirst().map(StackWalker.StackFrame::getDeclaringClass)
);
return caller.get();
}
If you need the class of the calling method use skip=1.
From a stack trace: http://www.javaworld.com/javaworld/javatips/jw-javatip124.html
A hacky solution is sun.reflect.Reflection.getCallerClass.
public void foo() {
Class<?> caller = sun.reflect.Reflection.getCallerClass();
// ...
}
It is hacky because you have to ensure that the class that calls Reflection.getCallerClass() is loaded on the bootstrap ClassLoader for the annotation #CallerSensitive (which getCallerClass is tagged with) to work. As such, it probably isn't the best solution for a project unless your project happens to use a Java Agent to add your classes to the bootstrap ClassLoader search.
With the following code, you obtain the first class which generated the stack of calls:
public String getInvonkingClassName(boolean fullClassNameNeeded){
StackTraceElement[] stack = new Exception().getStackTrace();
String className = stack[stack.length-1].getClassName();
if(!fullClassNameNeeded){
int idx = className.lastIndexOf('.');
className = className.substring(idx+1);
}
return className;
}
Boolean argument is used to get the full name including package name, or just class name.
StackFrame
The state of one method invocation on a thread's call stack. As a thread executes, stack frames are pushed and popped from its call stack as methods are invoked and then return. A StackFrame mirrors one such frame from a target VM at some point in its thread's execution.
JVM Stack: From Frame 1 get Frame 2 details
| |
| |
| Class2.function1() [FRAME 1] |
| executing the instructions |
|-------------------------------------------|
|Class1.method1() [FRAME 2] |
| called for execution Class2.function1() |
|-------------------------------------------|
Throwable::getStackTrace and Thread::getStackTrace return an array of StackTraceElement objects, which contain the class name and method name of each stack-trace element.
Throwable::getStackTrace contains the Stack with frames as Frame1(Top Frame) Current method, Frame2 calls Frame1 method for execution.
StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace();
// Frame1:Log4J.log(), Frame2:CallerClass
Thread::getStackTrace contains the stack with Frames:
Frame1:Thread.getStackTrace(), Frame2:Current Method, Frame3:Caller Method
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); //
sun.misc.SharedSecrets.getJavaLangAccess()
sun.misc.JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
StackTraceElement frame = javaLangAccess.getStackTraceElement((new Throwable()), callerFrame-1 ); // Frame0:Log4J.log(), Frame1:CallerClass
System.out.format("SUN - Clazz:%s, Method:%s, Line:%d\n", frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
Throwable throwable = new Throwable();
int depth = javaLangAccess.getStackTraceDepth(new Throwable());
System.out.println("\tsun.misc.SharedSecrets : "+javaLangAccess.getClass() + " - StackTraceDepth : "+ depth);
for (int i = 0; i < depth; i++) {
StackTraceElement frame = javaLangAccess.getStackTraceElement(throwable, i);
System.out.format("Clazz:%s, Method:%s, Line:%d\n", frame.getClassName(), frame.getMethodName(), frame.getLineNumber());
}
JDK-internal sun.reflect.Reflection::getCallerClass method. It is deprecated, removed in Java9 JDK-8021946
Any way by using Reflection API we can't find the Line Number of Function which it get called.
System.out.println("Reflection - Called from Clazz : "+ Reflection.getCallerClass( callerFrame )); // Frame1:Log4J.log(), Frame2:CallerClass
Example:
static boolean log = false;
public static void log(String msg) {
int callerFrame = 2; // Frames [Log4J.log(), CallerClass.methodCall()]
StackTraceElement callerFrameStack = null;
StackTraceElement[] stackTraceElements = (new Throwable()).getStackTrace(); // Frame1:Log4J.log(), Frame2:CallerClass
//StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();// Frame1:Thread.getStackTrace(), Frame2:Log4J.log(), Frame3:CallerClass
int callerMethodFrameDepth = callerFrame; // Caller Class Frame = Throwable:2(callerFrame), Thread.currentThread:2(callerFrame+1)
for (int i = 0; i < stackTraceElements.length; i++) {
StackTraceElement threadFrame = stackTraceElements[i];
if (i+1 == callerMethodFrameDepth) {
callerFrameStack = threadFrame;
System.out.format("Called form Clazz:%s, Method:%s, Line:%d\n", threadFrame.getClassName(), threadFrame.getMethodName(), threadFrame.getLineNumber());
}
}
System.out.println(msg);
if (!log){
Logger logger = Logger.getLogger(callerFrameStack.getClass());
logger.info(msg);
}
}
public static void main(String[] args) {
Log4J.log("Log4J, main");
Clazz1.mc1();
Clazz21.mc12();
Clazz21.mc11();
Clazz21.mc21();
}
}
class Clazz1 {
public static void mc1() {
Log4J.log("Clazz1 - mc1");
}
}
class Clazz11 {
public static void mc11() {
Log4J.log("Clazz11 - mc11");
}
public static void mc12() {
Log4J.log("Clazz11 - mc12");
Clazz1.mc1();
}
}
class Clazz21 extends Clazz11 {
public static void mc21() {
Log4J.log("Clazz21 - mc21");
}
}
For Java 9 use Stack Walking API
I'm just answering this because for some reason the above answers started referring to exception handling - the original question had nothing to do with exceptions.
So, instead of trying to determine the caller of the method in question, and specifically to give more information dealing with the creation of a base class that generates SQL statements for its derived classes, here is an OO solution...
Make the base class abstract and include abstract methods that return the data it needs to build a sql statement.
This would include methods like...
getColumnList()
getFromTable()
getJoinedTables()
getFilterColumns()
The base class then does not care who is calling it because it is going to call up to the derived class for all the details it needs to create the SQL statement.
The base class knows the derived classes are going to provide the implementation of these methods because they are abstract.
Another way to implement this would be to have a SQLGenerator class that receives an interface with the methods described above and operates on the instances passed to it via those methods. For this, you would want to have the abstract methods described above moved into the interface, which all of your SQL related classes would implement.
List item
I tried this and it works well. It is because each Java Object has access to getClass() method which returns the class caller and the method name.
public Logger logger() {
return Logger.getLogger(getClass().toString());
}
example usage:
public DBTable(String tableName) {
this.tableName = tableName;
loadTableField();
this.logger().info("done");
}
sample output log using java.util.logging.Logger
Feb 01, 2017 11:14:50 PM rmg.data.model.DBTable (init) INFO: done
Maybe an answer is
public class CallerMain {
public void foo(){
System.out.println("CallerMain - foo");
System.out.println(this.getClass()); //output- callerMain
}
public static void main(String[] args) {
A a = new A();
CallerMain cm = new CallerMain();
cm.foo();
}
}
class A{
public void foo(){
System.out.println("A - foo");
System.out.println(this.getClass());//output- A
}
}