As we know, in Java, method name is not sufficient to distinguish different methods.
I think (may be wrong), to distinguish a method, it needs the following info:
(className, methodName, methodParameters)
Further,
how to identify a method more efficiently internally?
I heard of "method id". Does it mean there is a mapping between the above triple and an integer, so JVM use only method id after parsing?
If so, is it resided in symbol table?
Thanks!
It's a CONSTANT_NameAndType_info Structure pointing at a method descriptor.
It pretty much consists of the method name, the parameter types, and (somewhat surprisingly) the return type.
I do not understand very well what you are trying to do but I think there are some possible answers nonetheless:
You may be interested in the JNI Method Descriptors, one of the various string formats used internally by the JVM (and by JNI libraries) for identifying Java elements.
It is difficult to know about what you are talking about. The "method id" can be a reference for a java.lang.reflect.Method object, or can be the method descriptor mentioned below, or any other thing. Where did you read about it?
I doubt there is such table inside the JVM. I mean, I doubt there is a global table, because almost always you retrieve a method from a class, even when dealing with it inside the JVM, so it is reasonable to believe the method is stored in the class. It is likewhen we use reflection to retrieve a method:
Class clazz = String.class;
Method method = clazz.getDeclaredMethod("charAt", Integer.TYPE);
System.out.println(method.getName());
Note that I ask the class String for the method, instead of asking some util class to give me the method charAt, which receives an int and is from the class String.
In other words, your identification tuple is almost correct - it just does not have a class:
(methodName, methodParameters)
and, instead of retrieving the method from the JVM passing the class and then the method name and then the parameter types, you retrieve the method directly from the class, giving the class the method name and the parameter types. A subtle difference, for sure, but I think it is what you are wondering about.
This is evident even in the JNI descriptors I mentioned below. For example, the method
long f(int i, Class c);
is represented by the following descriptor:
"(ILjava/lang/Class;)J"
Note that there is no reference to the class of the method.
The excellent documentation on the class file format (already pointed by #Lawence) may give you some insights. I recommend you to read it fully.
1) How to identify a method more efficiently internally?
Internally to what? There are many places where a method might need to be "identified" "internally". In the bytecode compiler, the JIT compiler, the classloader / linker, the classfile representation, reflection API, a debugger and so on. They each have different efficiency concerns.
2) I heard of "method id". Does it mean there is a mapping between the above triple and an integer, so JVM use only method id after parsing?
A method id is used in the classfile representation, and could be used by anything based on that, including the class loader / linker, the JIT compiler and the debugger.
The JVM doesn't parse Java code.
3) If so, is it resided in symbol table?
It might do. It depends on what you mean by "the symbol table". Bear in mind that there are lots of places where method identification is required, throughout the lifecycle of a class. For instance, the Java reflection APIs require method information to implement methods such as getDeclaredMethod(...) and various methods of Method.
Java always differentiate its language elements by their fully qualified names.
Suppose you have a method myMethod(int a, int b) in class MyClass which lies in the package com.mypackage then java will identify the method with the name com.mypackage.MyClass.myMethod(int a , int b).
Just to give you some more insight, it also takes the Class Loader into consideration when there is a need to resolve two identical elements.
It does consider, which class loader was used to load the particular class containing the method to which you are referring. There are four types of class loaders in java. You can read the documention for java.lang.Thread class for this.
Related
Preface
I have been experimenting with ByteBuddy and ASM, but I am still a beginner in ASM and between beginner and advanced in ByteBuddy. This question is about ByteBuddy and about JVM bytecode limitations in general.
Situation
I had the idea of creating global mocks for testing by instrumenting constructors in such a way that instructions like these are inserted at the beginning of each constructor:
if (GlobalMockRegistry.isMock(getClass()))
return;
FYI, the GlobalMockRegistry basically wraps a Set<Class<?>> and if that set contains a certain class, then isMock(Class<?>> clazz) would return true. The advantage of that concept is that I can (de)activate global mocking for each class during runtime because if multiple tests run in the same JVM process, one test might need a certain global mock, the next one might not.
What the if(...) return; instructions above want to achieve is that if mocking is active, the constructor should not do anything:
no this() or super() calls, โ update: impossible
no field initialisations, โ update: possible
no other side effects. โ update: might be possible, see my update below
The result would be an object with uninitialised fields that did not create any (possibly expensive) side effects such as resource allocation (database connection, file creation, you name it). Why would I want that? Could I not just create an instance with Objenesis and be happy? Not if I want a global mock, i.e. mock objects I cannot inject because they are created somewhere inside methods or field initialisers I do not have control over. Please do not worry about what method calls on such an object would do if its instance fields are not properly initialised. Just assume I have instrumented the methods to return stub results, too. I know how to do that already, the problem are only constructors in the context of this question.
Questions / problems
Now if I try to simulate the desired result in Java source code, I meet the following limitations:
I cannot insert any code before this() or super(). I could mitigate that by also instrumenting the super class hierarchy with the same if(...) return;, but would like to know if I could in theory use ASM to insert my code before this() or super() using a method visitor. Or would the byte code of the instrumented class somehow be verified during loading or retransformation and then rejected because the byte code is "illegal"? I would like to know before I start learning ASM because I want to avoid wasting time for an idea which is not feasible.
If the class contains final instance fields, I also cannot enter a return before all of those fields have been initialised in the constructor. That might happen at the very end of a complex constructor which performs lots of side effects before actually initialising the last field. So the question is similar to the previous one: Can I use ASM to insert my if(...) return; before any fields (including final ones) are initialised and produce a valid class which I could not produce using javac and will not be rejected when loaded or retransformed?
BTW, if it is relevant, we are talking about Java 8+, i.e. at the time of writing this that would be Java versions 8 to 14.
If anything about this question is unclear, please do not hesitate to ask follow-up questions, so I can improve it.
Update after discussing Antimony's answer
I think this approach could work and avoid side effects, calling the constructor chain but avoiding any side effects and resulting in a newly initialised instance with all fields empty (null, 0, false):
In order to avoid calling this.getClass(), I need to hard-code the mock target's class name directly into all constructors up the parent chain. I.e. if two "global mock" target classes have the same parent class(es), multiple of the following if blocks would be woven into each corresponding parent class, one for each hard-coded child class name.
In order to avoid any side effects from objects being created or methods being called, I need to call a super constructor myself, using null/zero/false values for each argument. That would not matter because the next parent class up the chain would have a similar code block so that the arguments given do not matter anyway.
// Avoid accessing 'this.getClass()'
if (GlobalMockRegistry.isMock(Sub.class)) {
// Identify and call any parent class constructor, ideally a default constructor.
// If none exists, call another one using default values like null, 0, false.
// In the class derived from Object, just call 'Object.<init>'.
super(null, 0, false);
return;
}
// Here follows the original byte code, i.e. the normal super/this call and
// everything else the original constructor does.
Note to myself: Antimony's answer explains "uninitialised this" very nicely. Another related answer can be found here.
Next update after evaluating my new idea
I managed to validate my new idea with a proof of concept. As my JVM byte code knowledge is too limited and I am not used to the way of thinking it requires (stack frames, local variable tables, "reverse" logic of first pushing/popping variables, then applying an operation on them, not being able to easily debug), I just implemented it in Javassist instead of ASM, which in comparison was a breeze after failing miserably with ASM after hours of trial & error.
I can take it from here and I want to thank user Antimony for his very instructive answer + comments. I do know that theoretically the same solution could be implemented using ASM, but it would be exceedingly difficult in comparison because its API is too low level for the task at hand. ByteBuddy's API is too high level, Javassist was just right for me in order to get quick results (and easily maintainable Java code) in this case.
Yes and no. Java bytecode is much less restrictive than Java (source) in this regard. You can put any bytecode you want before the constructor call, as long as you don't actually access the uninitialized object. (The only operations allowed on an uninitialized this value are calling a constructor, setting private fields declared in the same class, and comparing it against null).
Bytecode is also more flexible in where and how you make the constructor call. For example, you can call one of two different constructors in an if statement, or you can wrap the super constructor call in a "try block", both things that are impossible at the Java language level.
Apart from not accessing the uninitialized this value, the only restriction* is that the object has to be definitely initialized along any path that returns from the constructor call. This means the only way to avoid initializing the object is to throw an exception. While being much laxer than Java itself, the rules for Java bytecode were still very deliberately constructed so it is impossible to observe uninitialized objects. In general, Java bytecode is still required to be memory safe and type safe, just with a much looser type system than Java itself. Historically, Java applets were designed to run untrusted code in the JVM, so any method of bypassing these restrictions was a security vulnerability.
* The above is talking about traditional bytecode verification, as that is what I am most familiar with. I believe stackmap verification behaves similarly though, barring implementation bugs in some versions of Java.
P.S. Technically, Java can have code execute before the constructor call. If you pass arguments to the constructor, those expressions are evaluated first, and hence the ability to place bytecode before the constructor call is required in order to compile Java code. Likewise, the ability to set private fields declared in the same class is used to set synthetic variables that arise from the compilation of nested classes.
If the class contains final instance fields, I also cannot enter a return before all of those fields have been initialised in the constructor.
This, however, is eminently possible. The only restriction is that you call some constructor or superconstructor on the uninitialized this value. (Since all constructors recursively have this restriction, this will ultimately result in java.lang.Object's constructor being called). However, the JVM doesn't care what happens after that. In particular, it only cares that the fields have some well typed value, even if it is the default value (null for objects, 0 for ints, etc.) So there is no need to execute the field initializers to give them a meaningful value.
Is there any other way to get the type to be instantiated other than this.getClass() from a super class constructor?
Not as far as I am aware. There's no special opcode for magically getting the Class associated with a given value. Foo.class is just syntactic sugar which is handled by the Java compiler.
Trying to relearn C++ after a long-term dose of Java, I've read on SO and also vaguely remember that when a class is declared in a header file and defined in a cpp file, that splits its interface (the h file) from its implementation (the cpp file).
But how can the h file be considered an interface if it contains private member variable declarations? The choice of member variables constrains the implementation, does it not? A different implementation may use an entirely different set of variables.
For example, a complex number class could be implemented with real and imaginary variables, or with magnitude and argument variables, yet support the same set of getters and setters and what have you.
Wouldn't the only way of separating interface from implementation be by inheriting pure-virtuals from a base class akin to Java's interfaces?
No. Header Files and interfaces were constructed in C long before C++. A common methodology of doing this in C land is through opaque types. Where an object has a pointer to something that is defined as char** or char[x] only denoting the size for you so you can't see it. Good examples include most anything related to Sybase and IBM middleware. You can't 'construct' objects directly, you have to go through their factory methods.
In C++ this is often realized via the Pimpl pattern and private members. While you can still see some of the bits; you can still program against the interface. Furthermore not EVERY type will be exposed to you. Its not as cut and dry.
Like anything else there are trade-offs. With Interfaces ( which more accurately turns into a templated class IMHO) every single function has to be defined over and over again for every child class; this is good for run-time performance. You can also do a abstract base class composed entirely of pure virtual functions; and this is indeed in many ways an interface; except you've also taken on the cost of virtual function look-ups for everything, some people don't like this.
You could argue points both ways till the cows come home... people write exhaustive papers on this stuff.
In the end I would argue you are taking Java too literally as to what an INTERFACE is. While there often isn't a concrete thing in a header that says literally "i am an interface" its often there and can be gleaned and discovered purely from the headers.
It's also noteworthy as an interface because with the headers and shared object you can know how to 'use' the classes and compile against them without having the source code. So again, it is an interface; just not always as "pure" as the one you see in java.
I'm familiar with various ways of intercepting method invocations using proxies, but I'm wondering if there's a way to detect field access / dereferences on some proxy using a library like Javassist or ASM? For example:
void detectFieldName(Function<Foo, Supplier<String>> f) {
Foo fooProxy = createFooProxy();
f.apply(fooProxy);
}
detectFieldName((Foo foo) -> foo.bar);
Ideally from this I'd like to know that a field named bar was dereferenced.
Looking at your updated use case: lambdas are desugared to synthetic (compiler-generated) methods, with a function object that forwards interface calls through the generated method (I haven't looked into exactly how this is implemented, but I think Brian Goetz has talked about it). You can just look in that method's bytecode (loaded from the class file; some of the ASM sample code does this) and read off the field access. Instrumentation is not required.
Note that you can't create a proxy to see field access; the field access is performed in the lambda method (or more generally, where the field is loaded) without executing any code in Foo. In fact, you don't even need to call the lambda if all you want is to get the field name, and if all you're using the Foo proxy for is the call, you don't need a proxy.
I'm not aware of any way to intercept field accesses as easily as java.lang.reflect.Proxy makes intercepting method calls.
The getfield and putfield bytecodes use symbolic descriptors that encode the class and field name, so you could use a Java agent to add method calls before or after each load and store passing the field name, object and value being loaded/stored. (This works best if you're only interested in a subset of fields, say all fields of a particular class.) Depending on your needs, you may also have to recognize reflective accesses to your fields by instrumenting use of java.lang.reflect.Field, the handle returned by MethodHandles.Lookup.findGetter/Setter etc. (which may involve interprocedural analysis or reasoning about string operations used to build the field name, etc.). You could also try instrumenting "just before" the library calls into some JVM-specific native functionality, but that ties you to one JVM implementation and your instrumentation may be skipped if the JVM intrinsifies (special-cases codegen for) reflective calls.
If you're willing to write C code, you can use the JVM Tool Interface watched field functions. This seems the easiest way to get information, but it's harder to do interesting Java-level things with (though you can call back into your Java support library from the JVMTI).
Without major hacks, this is not possible. Field access in Java is not bound dynamically. This means, any reading or writing to a field is hardcoded into all using classes. With a method proxy, one makes use of the fact you can override a method to determine behavior. For intercepting field access, one would need to intercept the class that is using a field. Some libraries emulate this behavior by replacing field access by synthetic accessor methods. This requires however some build time redefinition of all concerned classes throughout the entire project.
As for your example, you could in theory use a tool like ASM to extract the required information from the lambda expression. However, note that the lambda expression's code will be extracted into a method of the class of the method that uses the lambda expression. You might have trouble finding out which method it actually is that contains your lambda but the byte code for invoking the expression will merely look something like this:
InvokeDynamic #0:accept:(LFoo;)Ljava/util/function/Function;
As you can see, the byte code will only contain a possibly ambiguous signature. Otherwise, you could of course copy the lambda expression's logic into a new class where you changed the logic of a field access. Since lambdas are by definition interfaces, the creation of such a new class would actually be comparably easy. But the problem with the method detection remains.
I noticed that if I have two methods with the same name, the first one accepts SomeObject and the second one accepts an object extending SomeObject when I call the method with SomeOtherObject, it automatically uses the one that only accepts SomeObject. If I cast SomeOtherObject to SomeObject, the method that accepts SomeObject is used, even if the object is an instanceof SomeOtherObject. This means the method is selected when compiling. Why?
That's how method overload resolution in Java works: the method is selected at compile time.
For all of the ugly details, see the Java Language Specification ยง15.12.
This means the method is selected when compiling.
Yes you are correct. That is what it means.
Why?
I can think of four reasons why they designed Java this way:
This is consistent with the way that other statically typed OO languages that support overloading work. It is what people who come / came from the C++ world expect. (This was particularly important in the early days of Java ... though not so much now.). It is worth noting that C# handles overloading the same way.
It is efficient. Resolving method overloads at runtime (based on actual argument types) would make overloaded method calls expensive.
It gives more predictable (and therefore more easy to understand) behaviour.
It avoids the Brittle Base Class problem, where adding adding a new overloaded method in a base class causes unexpected problems in existing derived classes.
References:
http://blogs.msdn.com/b/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx
Yes the function to be executed is decided at compile time! So JVM has no idea of the actual type of the Object at compile time. It only knows the type of the reference that points to the object given as argument to the function.
For more details you can look into Choosing the Most Specific Method in Java Specification.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is a class literal in Java?
I was going through literals in the Java tutorial where I came across this sentence:
Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.
Which doesn't make any sense to me, even though I paid attention to all the other topics prior to this. Can anyone explain in simple language with examples or references?
Instances of the class java.lang.Class represent classes and interfaces in a running Java application. For each class in the application, there is an instance of Class. The SomeClass.class syntax is a way to get from SomeClass to the corresponding instance of Class.
A class literal is just a special type to use when you want to do something involving the class itself, rather than an instance.
Here's a short list of a few things I commonly use this for (not at all comprehensive, but you can get a good idea)
1.) Reflection, you want to instantiate something in run-time that you may not know (perhaps it was stored in a variable of type Class)
2.) You want to check if 2 objects are of the same related type, you can write something along the lines of: B.class.isAssignableFrom(a.getClass());
3.) You want to list all the methods, or public variables within a class, perhaps for documentation.
There are many other uses, but these are the main ones I find myself using in common practice.
Speaking simple language: that thing, which you call class literal is an object which fully describes some class: all its methods, all its fields, all its annotations, class's modifiers and so on. It is needed for creating new instances of that class in runtime.
Short example:
Class x = String.class;
System.out.println(x);
you can use x to create runtime instances of the class it points to or to test the class of an object against it.
It evaluates to be the class identifier of the reference or primitive type's wrapper class. The expression void.class evaluates to the class identifier of the Void class. Same thing with 'String.class'