I would like to write a code internal to my method that print which method/class has invoked it.
(My assumption is that I can't change anything but my method..)
How about other programming languages?
EDIT: Thanks guys, how about JavaScript? python? C++?
This is specific to Java.
You can use Thread.currentThread().getStackTrace(). This will return an array of StackTraceElements.
The 2nd element in the array will be the calling method.
Example:
public void methodThatPrintsCaller() {
StackTraceElement elem = Thread.currentThread.getStackTrace()[2];
System.out.println(elem);
// rest of you code
}
If all you want to do is print out the stack trace and go hunting for the class, use
Thread.dumpStack();
See the API doc.
Justin has the general case down; I wanted to mention two special cases demonstrated by this snippit:
import java.util.Comparator;
public class WhoCalledMe {
public static void main(String[] args) {
((Comparator)(new SomeReifiedGeneric())).compare(null, null);
new WhoCalledMe().new SomeInnerClass().someInnerMethod();
}
public static StackTraceElement getCaller() {
//since it's a library function we use 3 instead of 2 to ignore ourself
return Thread.currentThread().getStackTrace()[3];
}
private void somePrivateMethod() {
System.out.println("somePrivateMethod() called by: " + WhoCalledMe.getCaller());
}
private class SomeInnerClass {
public void someInnerMethod() {
somePrivateMethod();
}
}
}
class SomeReifiedGeneric implements Comparator<SomeReifiedGeneric> {
public int compare(SomeReifiedGeneric o1, SomeReifiedGeneric o2) {
System.out.println("SomeRefiedGeneric.compare() called by: " + WhoCalledMe.getCaller());
return 0;
}
}
This prints:
SomeRefiedGeneric.compare() called by: SomeReifiedGeneric.compare(WhoCalledMe.java:1)
somePrivateMethod() called by: WhoCalledMe.access$0(WhoCalledMe.java:14)
Even though the first is called "directly" from main() and the second from SomeInnerClass.someInnerMethod(). These are two cases where there is a transparent call made in between the two methods.
In the first case, this is because we are calling the bridge method to a generic method, added by the compiler to ensure SomeReifiedGeneric can be used as a raw type.
In the second case, it is because we are calling a private member of WhoCalledMe from an inner class. To accomplish this, the compiler adds a synthetic method as a go-between to override the visibility problems.
the sequence of method calls is located in stack. this is how you get the stack: Get current stack trace in Java then get previous item.
Since you asked about other languages, Tcl gives you a command (info level) that lets you examine the call stack. For example, [info level -1] returns the caller of the current procedure, as well as the arguments used to call the current procedure.
In Python you use the inspect module.
Getting the function's name and file name is easy, as you see in the example below.
Getting the function itself is more work. I think you could use the __import__ function to import the caller's module. However you must somehow convert the filename to a valid module name.
import inspect
def find_caller():
caller_frame = inspect.currentframe().f_back
print "Called by function:", caller_frame.f_code.co_name
print "In file :", caller_frame.f_code.co_filename
#Alternative, probably more portable way
#print inspect.getframeinfo(caller_frame)
def foo():
find_caller()
foo()
Yes, it is possible.
Have a look at Thread.getStackTrace()
In Python, you should use the traceback or inspect modules. These will modules will shield you from the implementation details of the interpreter, which can differ even today (e.g. IronPython, Jython) and may change even more in the future. The way these modules do it under the standard Python interpreter today, however, is with sys._getframe(). In particular, sys._getframe(1).f_code.co_name provides the information you want.
Related
I am coming from Java and C++ background. However, I am doing a C# application at the moment and one thing made me confused.
In Java when I import a package, it means I can access the classes that are placed in that package. For example, here I imported the ArrayList class from package java.util.
import java.util.ArrayList;
class ArrayListUtilization {
public static void main(String[] args) {
ArrayList<Integer> myList = new ArrayList<>(3);
myList.add(3);
myList.add(2);
myList.add(1);
System.out.println(myList);
}
}
Recently I had a problem in my c-sharp app, that I asked here. The funny part in my point of view is, when I added the following snippet of code:
var accountDbContext = services.GetRequiredService<AccountDbContext>();
accountDbContext.Database.EnsureCreated();
var accountDbCreator = accountDbContext.GetService<IRelationalDatabaseCreator>();
accountDbCreator.CreateTables();
I saw an error as following:
Error CS1929 'AccountDbContext' does not contain a definition for
'GetService' and the best extension method overload
'ServiceProviderServiceExtensions.GetService(IServiceProvider)'
requires a receiver of type 'IServiceProvider'
and from the error text, I understood accountDbContext object does not have GetService function. But when I press on show potential fixes, then it suggests me to add a using statement.
And it was the real fix. However, my question is what is the effect of this using statement on my object? The object is an instantiation of its class. How can adding a using statement effect on my object and add a function to it?
Note that what you are actually calling an extension method here:
accountDbContext.GetService<IRelationalDatabaseCreator>();
accountDbContext does not have a method called GetService. GetService is declared in AccessorExtensions, and the above line is just syntactic sugar for:
AccessorExtensions.GetService<IRelationalDatabaseCreator>(accountDbContext);
Now it should make sense that you need to add a using directive for the class in which the extension method is declared, in order to access the extension method.
how can i send a command to a function , for example .
{
{
boolean b;
Do(b, b = false);
}
public void Do (boolean b,Command command)
{
if (b == true)
{
command;
}
}
}
so if b = true it should turn it to false in this example .
any ideas ?
i am using android studio - java
Thanks
First, define the structure of your command. You need to define the exact # and types of each argument your 'command' is to take, what an invocation of 'command' returns (which type), and which checked exceptions it is allowed to throw, if any.
Once you've decided on that, either find an appropriate existing functional interface, or make one yourself.
What is a functional interface? Simply an interface that has exactly 1 (non-default) method in it. For example, there is java.lang.Runnable defined like so:
public interface Runnable {
void run();
}
which means: This command takes no arguments, returns nothing, and cannot throw any checked exceptions.
Once you've done all that you can create them fairly easily. This acts like an object, so you can just call .run() on the result:
public void test() {
Runnable r = () -> System.out.println("Hello!");
doTwice(r);
// you can one-liner it too of course:
doTwice(() -> System.out.println("World!"));
}
public void doTwice(Runnable r) {
r.run();
r.run();
}
The above will print 'Hello!' twice and then 'World!' twice.
However, in your pseudocode you are trying to change a value of a local variable inside the code you 'send' to the other method. This is not allowed in java; any local variables used in one of these code blocks needs to be effectively final, which means: They are initialized exactly once and never changed again.
A way out of the dilemma is to make that an AtomicBoolean which is a mutable object. Then you'd get something like:
AtomicBoolean b = new AtomicBoolean(false);
runTwice(()-> b.set(true));
System.out.println(b); // Prints true
You've asked about android; the above features were introduced in java 8. While java 8 is almost 5 years old by now, android is more or less a fork of java and it was forked before java 8 was introduced. I don't know if android supports these constructs. Google or ask around if android supports 'lambdas' (which is what the above stuff does).
If android does not support lambdas, it's still possible but real, real ugly:
runTwice(new Runnable() {
public void run() {
System.out.println("Hello!");
}
});
I use ASM to update the class stack map, but when asm getMergedType, the following exception occurs:
java.lang.RuntimeException:
java.io.IOException: Resource not found for IntefaceImplA.
If without asm modify the class method, it does work fine.
I have defined two interfaces A and B: IntefaceImplA and
IntefaceImplB.
My environment source code:
IntefaceA.java
public interface IntefaceA {
void inteface();
}
IntefaceImplA.java
public class IntefaceImplA implements IntefaceA {
#Override
public void inteface() {
}
}
IntefaceImplB.java
public class IntefaceImplB implements IntefaceA {
#Override
public void inteface() {
}
}
Test.java
public class Test {
public IntefaceA getImpl(boolean b) {
IntefaceA a = b ? new IntefaceImplA() : new IntefaceImplB();
return a;
}
}
Main.java
public class Main {
public static void main(String args[]) {
....
if (a instance of Test) {
..
...
}
}
}
After I compiled a runner jar, and delete the IntefaceImplA.class and IntefaceA.class manually from the jar. why i wanna to delete those classes files, since the spring always like to do this stuff.
the runner jar can be run normal without ASM, but use Asm will occur exception. since the asm wanna to getMergedType for IntefaceImplA and IntefaceImplB, but IntefaceImplA was deleted by me.
After investigate the ASM ClassWriter source code i found below code:
protected String getCommonSuperClass(String type1, String type2)
{
ClassLoader classLoader = this.getClass().getClassLoader();
Class c;
Class d;
try {
c = Class.forName(type1.replace('/', '.'), false, classLoader);
d = Class.forName(type2.replace('/', '.'), false, classLoader);
} catch (Exception var7) {
throw new RuntimeException(var7.toString());
}
if(c.isAssignableFrom(d)) {
return type1;
} else if(d.isAssignableFrom(c)) {
return type2;
} else if(!c.isInterface() && !d.isInterface()) {
do {
c = c.getSuperclass();
} while(!c.isAssignableFrom(d));
return c.getName().replace('.', '/');
} else {
return "java/lang/Object";
}
}
Actually, I deleted the related class file, the classloader cannot find the class. but without asm the Program does work normal.
Should I enhance the override to the getCommonSuperClass method, if occur exception then return java/lang/Object for it? that's funny
Generally, overriding getCommonSuperClass to use a different strategy, e.g. without loading the class, is a valid use case. As it’s documentation states:
The default implementation of this method loads the two given classes and uses the java.lang.Class methods to find the common super class. It can be overridden to compute this common super type in other ways, in particular without actually loading any class, or to take into account the class that is currently being generated by this ClassWriter, which can of course not be loaded since it is under construction.
Besides the possibility that either or both arguments are classes you are currently constructing (or changing substantially), it might be the case that the context of the code transforming tool is not the context in which the classes will eventually run, so they don’t have to be accessible via Class.forName in that context. Since Class.forName uses the caller’s context, which is ASM’s ClassWriter, it is even possible that ASM can’t access the class despite it is available in the context of the code using ASM (if different class loaders are involved).
Another valid scenario is to have a more efficient way to resolve the request by using already available meta information without actually loading the class.
But, of course, it is not a valid resolution to just return "java/lang/Object". While this is indeed a common super type of every argument, it isn’t necessarily the right type for the code. To stay with your example,
public IntefaceA getImpl(boolean b) {
IntefaceA a = b ? new IntefaceImplA() : new IntefaceImplB();
return a;
}
the common super type of IntefaceImplA and IntefaceImplB is not only required to verify the validity of assigning either type to it, it is also the result type of the conditional expression, which must be assignable to the return type of the method. If you use java/lang/Object as common super type, a verifier will reject the code as it can’t be assignable to IntefaceA.
The original stackmap, very likely reporting IntefaceA as common super, will be accepted by the verifier as that type is identical to the method’s return type, so it can be considered assignable, even without loading the type. The test, whether either, IntefaceImplA and IntefaceImplB, is assignable to that specified common type, might be postponed to the point where these types are actually loaded and since you said, you deleted IntefaceA, this can never happen.
A method whose declared return type is absent, can’t work at all. The only explanation of your observation that “without asm the program does work normal”, is, that this method was never invoked at all during your test. You most probably created a time bomb in your software by deleting classes in use.
It’s not clear why you did this. Your explanation “since the spring always like to do this stuff” is far away from being comprehensible.
But you can use the overriding approach to get the same behavior as with the unmodified code. It just doesn’t work by return java/lang/Object. You could use
#Override
protected String getCommonSuperClass(String type1, String type2) {
if(type1.matches("IntefaceImpl[AB]") && type2.matches("IntefaceImpl[AB]"))
return "IntefaceA";
return super.getCommonSuperClass(type1, type2);
}
Of course, if you deleted more class files, you have to add more special cases.
An entirely different approach is not to use the COMPUTE_FRAMES option. This option implies that ASM will recompute all stack map frames from scratch, which is great for the lazy programmer, but implies a lot of unnecessary work if you are just doing little code transformations on an existing class and, of course, creates the requirement to have a working getCommonSuperClass method.
Without that option, the ClassWriter will just reproduce the frames the ClassReader reports, so all unchanged methods will also have unchanged stack maps. You will have to care about the methods whose code you change, but for a lot of typical code transformation tasks, you can still keep the original frames. E.g. if you just redirect method calls to signature-compatible targets or inject logging statements which leave the stack in the same state it was before them, you can still keep the original frames, which happens automatically. Note the existence of the ClassWriter(ClassReader,int) constructor, which allows an even more efficient transfer of the methods you don’t change.
Only if you change the branch structure or insert code with branches, you have to care for frames. But even then, it’s often worth learning how to do this, as the automatic calculation is quiet expensive while you usually have the necessary information already when doing a code transformation.
In my java code there is class A that has the following line:
Process localProcess = Runtime.getRuntime().exec(myString);
where myString is user supplied input and is passed to exec() at runtime.
Also there is a public method doSomething() in class A.
Can I somehow invoke doSomething() (through reflection, jdwp etc.) using exec() at runtime ?
Starting a new JVM just to call a single method? First, that would be really slow. And second, it would be highly unnecessary!
Reflection is what you want I guess. Here's some sample code.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Class<Main> c = Main.class; // First get the class
try {
Method method = c.getMethod("doSomething"); // get the method by its name
method.invoke(new Main()); // call it on a new instance of Main
} catch (NoSuchMethodException e) {
System.out.println("Method is not found"); // print something when the method is not found
}
}
public void doSomething() {
System.out.println("I have done something!");
}
}
That would mean starting a whole new JVM just to make a method call.
If you are already "within" class A; what prevents you from calling doSomething() directly? Probably: only your lack of skills. If so, then work on your skills; and don't go for the next best solution you heard somebody mention how things might be done!
In essence: a self-claimed geek should always understand each and any concept he is using in his programs. If you want to use reflection, then study what reflection is about.
And please note: letting your users pass in arbitrary strings to have them executed, is a huge security NO GO. You should have mentioned in your question that you want to do this on purpose; and that you are fully aware of the potential consequences of doing so!
EDIT; given your latest comments.
In this case, a solution could be as simple as:
A) you write a new class, like
public class Invoker {
public static void main(String[] args) {
A.doSomething();
or if doSomething isn't static, you will need
A someA = new A( ... however you can create instances of A
A.doSomething()
B) Compile that, and then you can simply send a command like
java -cp WHATEVER Invoker
into your existing application. Of course, you have to work out the details; like providing a valid classpath to that call to java (that classpath has to include the location where Invoker.class lives; and of course A.class; and all of the dependencies that A has).
But keep in mind: doSomething() is executed in the scope of a different JVM. That means that most likely, it will not at all affect class A in that JVM where you trigger the call to exec!
I'm using ASM Java library to generate a class X from scratch. Inside one of the static methods of this class I need to push a reference to X.class. Since there isn't yet a X.class I can't use visitLdcInsn. Is there a way to do it?
Well, it's possible (and I'm currently using it) to generate the following code (new X().getClass()), but I'm sure that's not the cleanest way to do it.
With generated code you usually don't need to push the class onto the stack. Anything you can do with a method call is usually available in byte code.
Say you have to call a method with a class, you can push it onto the stack whether it exists or not.
Something I use is the ASMifier. This is useful because you can start with a class which compiles and does what you want as a template and get it to dump all the code needed to recreate the class. This means you don't really need to write most of the code yourself.
public class Main {
public static void main(String... args) throws IOException {
ASMifierClassVisitor cv = new ASMifierClassVisitor(new PrintWriter(System.out));
ClassReader cr = new ClassReader("X");
cr.accept(cv, 0);
}
}
class X {
{
System.out.println("Inside class "+X.class);
}
}
prints
// lots of code
mv.visitLdcInsn(Type.getType("LX;"));
// more code.