Understanding dynamic polymorphsim byte code - java

I am a novice to Java byte code and would like to understand the following byte code of Dispatch.class relative to Dispatch.java source code below :
Compiled from "Dispatch.java"
class Dispatch {
Dispatch();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class B
3: dup
4: invokespecial #3 // Method B."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method A.run:()V
12: return
}
//=====================Dispatch.java==============================
class Dispatch{
public static void main(String args[]){
A var = new B();
var.run(); // prints : This is B
}
}
//======================A.java===========================
public class A {
public void run(){
System.out.println("This is A");
}
}
//======================B.java===========================
public class B extends A {
public void run(){
System.out.println("This is B");
}
}
After doing some reading on the internet I had a first grasp of how JVM stack and opcodes work. I still however do not get what these command lines are good for :
3: dup //what are we duplicating here exactly?
4: invokespecial #3 //what does the #3 in operand stand for?
invokevirtual VS invokespecial //what difference there is between these opcodes?

It really sounds like you need to read the docs some more, but to answer your updated questions,
dup duplicates the top value on the operand stack. In this case, it would be the uninitialized B object that was pushed by the previous new instruction.
The #3 means that invokespecial is operating on the 3rd slot in the classfile's constant pool. This is where the method to be invoked is specified. You can see the constant pool by passing -c -verbose to javap.
invokevirtual is used for ordinary (non interface) virtual method calls. (Ignoring default interface methods for the moment) invokespecial is used for a variety of special cases - private method calls, constructor invocations, and superclass method calls.

Related

What are the benefits of defining a variable on one line and create an instance of it on the next line

For example consider the slide from the Google I/O '17 "Android Animations Spring to Life":
SpringForce force = new SpringForce(0)
.setDampingRation(0.4f)
.setStiffness(500f);
for (int i = 0; i < heads.getChildCount(); i++) {
View child = heads.getChildAt(i);
SpringAnimation anim;
anim = new SpringAnimation(child, DynamicAnimation.ROTATION);
anim.setSpring(force).setStartValue(-25).start();
}
There we can see that variable anim is defined on one line and the instance of the variable is created on the next line. Sometimes I also see that approach in some open source projects.
Is there a real benefit of using that approach or it is just a matter of style or readability? Or, in the case of slides, it is a matter of fitting the width of the slide? But if that's so they could have written something like:
SpringAnimation anim = new SpringAnimation(
child, DynamicAnimation.ROTATION);
Let's do a little experiment. Given the following two classes:
public class Test {
public static void main(String... args) {
Integer i = Integer.valueOf(1);
System.out.println(i);
}
}
public class Test2 {
public static void main(String... args) {
Integer i;
i = Integer.valueOf(1);
System.out.println(i);
}
}
we can take a look at the generated bytecode:
> javac *.java && javap -c *.class
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String...);
Code:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: aload_1
9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
12: return
}
Compiled from "Test2.java"
public class Test2 {
public Test2();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String...);
Code:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: aload_1
9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
12: return
}
Since the generated bytecode is identical, it is a matter of personal preference.
Altho everyone have a good point on readability and good coding standard, the example provided shows that there are some objects that have mandatory and optional fields.
The code above could easily be put together in the same "line" like this:
Obj o = new Obj([mandatory args])
.optionalParam1(...)
.optionalParam2(...);
But the decided to separate the mandatory from the optional, so its more readable and well organized (or at least thats what I think).
They have proven that it doesn't matter because the code is the same at the end, so it us up to you to decide which practices work for you and which doesn't (I like to heavily comment on my code so is easier to come back, but I only do it in my personal projects because my workteam doesn't find it valuable if the code is clean and self explanatory).
Both answers from #Turing85 and #Kavita_p are good and they provide enough context and information for you!

When to declare objects?

I have been working on some of my AP cs projects and came to the wonder the difference between doing this:
public class CalculateTaxes {
private Scanner in;
public CalculateTaxes(){
in = new Scanner(System.in);
}
}
and this:
public class CalculateTaxes {
private Scanner in = new Scanner(System.in);
public CalculateTaxes(){
}
}
I've seen many examples were they declare an object in one line and instantiate it somewhere else in the code. Why not just declare and instantiate an object in the same line?
Lets test how these classes will be compiled.
public class Test1 {
private Scanner in;
public Test1() {
in = new Scanner(System.in);
}
}
and
public class Test2 {
private Scanner in = new Scanner(System.in);
public Test2() {
}
}
If we use javap -c Test1 we will see
Compiled from "Test1.java"
public class Test1 {
public Test1();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #12 // class java/util/Scanner
8: dup
9: getstatic #14 // Field java/lang/System.in:Ljava/io/InputStream;
12: invokespecial #19 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
15: putfield #22 // Field in:Ljava/util/Scanner;
18: return
}
and if we use it on Test2 we will get
Compiled from "Test2.java"
public class Test2 {
public Test2();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #12 // class java/util/Scanner
8: dup
9: getstatic #14 // Field java/lang/System.in:Ljava/io/InputStream;
12: invokespecial #19 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
15: putfield #22 // Field in:Ljava/util/Scanner;
18: return
}
So as you can see the initialization of in field in Test2 class was automatically moved by compiler at start of constructor.
In fact this code will be moved at start of each constructor of that class (right after super() call if any) so only difference is that if you have few constructors you can initialize in field in one place outside constructors instead of doing it in every one of them.
But if lets say you want to initialize field depending on some argument passed in constructor then you have to do it in constructors block.
If you intend to assign an object a value in one scope but need it to be visible in another it can be useful to split up the declaration and the assignment.
Pseudocode:
{
// Outer loop
SomeObject a;
if (condition_one == condition_two)
a = new SomeObject(4);
else
a = new SomeObject(12);
a.doStuff();
}
If a had been declared only inside of the if statements, it wouldn't be visible outside of that loop.
{
if (a == b)
SomeObject a = new SomeObject(5);
a.doStuff(); // ERROR
}
There's not much difference in this case. In some cases, you use different parameters depending on what parameters are sent in the constructor.
Ultimately, in a professional programming environment, your goal is not what is best "right now", but what will help you understand what's going on in 6 months when you need to reread your code and understand WHY you were doing something. HOW you implemented it will help document the intent.

Issue with constructors of nested class

This question is about interesting behavior of Java: it produces
additional (not default) constructor for nested classes in some
situations.
This question is also about strange anonymous class, which Java
produces with that strange constructor.
Consider the following code:
package a;
import java.lang.reflect.Constructor;
public class TestNested {
class A {
A() {
}
A(int a) {
}
}
public static void main(String[] args) {
Class<A> aClass = A.class;
for (Constructor c : aClass.getDeclaredConstructors()) {
System.out.println(c);
}
}
}
This will prints:
a.TestNested$A(a.TestNested)
a.TestNested$A(a.TestNested,int)
Ok. Next, lets make constructor A(int a) private:
private A(int a) {
}
Run program again. Receive:
a.TestNested$A(a.TestNested)
private a.TestNested$A(a.TestNested,int)
It is also ok. But now, lets modify main() method in such way (addition of new instance of class A creation):
public static void main(String[] args) {
Class<A> aClass = A.class;
for (Constructor c : aClass.getDeclaredConstructors()) {
System.out.println(c);
}
A a = new TestNested().new A(123); // new line of code
}
Then input becomes:
a.TestNested$A(a.TestNested)
private a.TestNested$A(a.TestNested,int)
a.TestNested$A(a.TestNested,int,a.TestNested$1)
What is it: a.TestNested$A(a.TestNested,int,a.TestNested$1) <<<---??
Ok, lets again make constructor A(int a) package local:
A(int a) {
}
Rerun program again (we don't remove line with instance of A creation!), output is as in the first time:
a.TestNested$A(a.TestNested)
a.TestNested$A(a.TestNested,int)
Questions:
1) How this could be explained?
2) What is this third strange constructor?
UPDATE: Investigation shown following.
1) Lets try to call this strange constructor using reflection from other class.
We will not able to do this, because there isn't any way to create instance of that strange TestNested$1 class.
2) Ok. Lets do the trick. Lets add to the class TestNested such static field:
public static Object object = new Object() {
public void print() {
System.out.println("sss");
}
};
Well? Ok, now we could call this third strange constructor from another class:
TestNested tn = new TestNested();
TestNested.A a = (TestNested.A)TestNested.A.class.getDeclaredConstructors()[2].newInstance(tn, 123, TestNested.object);
Sorry, but I absolutely don't understand it.
UPDATE-2: Further questions are:
3) Why Java use special anonymous inner class for an argument type for this third synthetic constructor? Why not just Object type, of constructor with special name?
4) What Java could use already defined anonymous inner class for those purposes? Isn't this some kind of violation of security?
The third constructor is a synthetic constructor generated by the compiler, in order to allow access to the private constructor from the outer class. This is because inner classes (and their enclosing classes' access to their private members) only exist for the Java language and not the JVM, so the compiler has to bridge the gap behind the scenes.
Reflection will tell you if a member is synthetic:
for (Constructor c : aClass.getDeclaredConstructors()) {
System.out.println(c + " " + c.isSynthetic());
}
This prints:
a.TestNested$A(a.TestNested) false
private a.TestNested$A(a.TestNested,int) false
a.TestNested$A(a.TestNested,int,a.TestNested$1) true
See this post for further discussion: Eclipse warning about synthetic accessor for private static nested classes in Java?
EDIT: interestingly, the eclipse compiler does it differently than javac. When using eclipse, it adds an argument of the type of the inner class itself:
a.TestNested$A(a.TestNested) false
private a.TestNested$A(a.TestNested,int) false
a.TestNested$A(a.TestNested,int,a.TestNested$A) true
I tried to trip it up by exposing that constructor ahead of time:
class A {
A() {
}
private A(int a) {
}
A(int a, A another) { }
}
It dealt with this by simply adding another argument to the synthetic constructor:
a.TestNested$A(a.TestNested) false
private a.TestNested$A(a.TestNested,int) false
a.TestNested$A(a.TestNested,int,a.TestNested$A) false
a.TestNested$A(a.TestNested,int,a.TestNested$A,a.TestNested$A) true
First of all, thank you for this interesting question. I was so intrigued that I could not resist taking a look at the bytecode. This is the bytecode of TestNested:
Compiled from "TestNested.java"
public class a.TestNested {
public a.TestNested();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc_w #2 // class a/TestNested$A
3: astore_1
4: aload_1
5: invokevirtual #3 // Method java/lang/Class.getDeclaredConstructors:()[Ljava/lang/reflect/Constructor;
8: astore_2
9: aload_2
10: arraylength
11: istore_3
12: iconst_0
13: istore 4
15: iload 4
17: iload_3
18: if_icmpge 41
21: aload_2
22: iload 4
24: aaload
25: astore 5
27: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
30: aload 5
32: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
35: iinc 4, 1
38: goto 15
41: new #2 // class a/TestNested$A
44: dup
45: new #6 // class a/TestNested
48: dup
49: invokespecial #7 // Method "<init>":()V
52: dup
53: invokevirtual #8 // Method java/lang/Object.getClass:()Ljava/lang/Class;
56: pop
57: bipush 123
59: aconst_null
60: invokespecial #9 // Method a/TestNested$A."<init>":(La/TestNested;ILa/TestNested$1;)V
63: astore_2
64: return
}
As you can see, the constructor a.TestNested$A(a.TestNested,int,a.TestNested$1) is invoked from your main method. Furthermore, null is passed as the value of the a.TestNested$1 parameter.
So let's take a look at the mysterious anonymous class a.TestNested$1:
Compiled from "TestNested.java"
class a.TestNested$1 {
}
Strange - I would have expected this class to actually do something. To understand it, let's take a look at the constructors in a.TestNested$A:
class a.TestNested$A {
final a.TestNested this$0;
a.TestNested$A(a.TestNested);
Code:
0: aload_0
1: aload_1
2: putfield #2 // Field this$0:La/TestNested;
5: aload_0
6: invokespecial #3 // Method java/lang/Object."<init>":()V
9: return
private a.TestNested$A(a.TestNested, int);
Code:
0: aload_0
1: aload_1
2: putfield #2 // Field this$0:La/TestNested;
5: aload_0
6: invokespecial #3 // Method java/lang/Object."<init>":()V
9: return
a.TestNested$A(a.TestNested, int, a.TestNested$1);
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #1 // Method "<init>":(La/TestNested;I)V
6: return
}
Looking at the package-visible constructor a.TestNested$A(a.TestNested, int, a.TestNested$1), we can see that the third argument is ignored.
Now we can explain the constructor and the anonymous inner class. The additional constructor is required in order to circumvent the visibility restriction on the private constructor. This additional constructor simply delegates to the private constructor. However, it cannot have the exact same signature as the private constructor. Because of this, the anonymous inner class is added to provide a unique signature without colliding with other possible overloaded constructors, such as a constructor with signature (int,int) or (int,Object). Since this anonymous inner class is only needed to create a unique signature, it does not need to be instantiated and does not need to have content.

How is the java "this" keyword implemented?

How does the this pointer points to the object itself? Is it a java implementation or is it a compiler implementation?
In the JVM bytecode, local variable 0 (basically register 0) points to the current object when a method is invoked. The compiler simply uses this as an alias for local variable 0.
So I guess the answer is that the compiler implements this.
Sounds like a philosophical question. I am not sure that a Java implementation is.
this is defined in the JLS and is a keyword in Java and the compile has to comply with that standard. When you have a method like
object.method(args)
what is actually called in byte code is a method which looks like
method(object, args);
where this is the first argument.
At the JVM level, the parameters don't have names and the JIT could optimise the argument away if its not actually used.
Well if you are interested why not look at the byte code generated by the compiler
class HelloWorld
{
private String hello = "Hello world!";
private void printHello(){
System.out.println (this.hello);
}
public static void main (String args[]){
HelloWorld hello = new HelloWorld();
hello.printHello();
}
}
Compile using
%JAVA_HOME%/bin/javac HelloWorld.java
Get bytecode using
javap -c HelloWorld
edit add output
enter code here
HelloWorld();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()
4: aload_0
5: ldc #2; //String Hello world!
7: putfield #3; //Field hello:Ljava/lang/String;
10: return
public static void main(java.lang.String[]);
Code:
0: new #6; //class HelloWorld
3: dup
4: invokespecial #7; //Method "<init>":()V
7: astore_1
8: aload_1
9: invokespecial #8; //Method printHello:()V
12: return
}

Why do the Java bytecodes for invoking methods implicitly acquire and release monitors?

I've been reading up on the Java Virtual Machine Instruction Set and noticed that when using instructions to invoke methods (e.g. invokestatic, invokevirtual, etc.) that are marked synchronized, it's up to that particular bytecode instruction to acquire the monitor on the receiver object. Similarly, when returning from a method, it's up to the instruction that leaves the method to release the monitor when the method is synchronized. This seems strange, given that there are explicit monitorenter and monitorexit bytecodes for managing monitors. Is there a particular reason for the JVM designing these instructions this way, rather than just compiling the methods to include the monitorenter and monitorexit instructions where appropriate?
Back in the mid-90s, there were no Java JIT compilers and micro-synchronisation was thought to be a really great idea.
So you are calling these synchronised method a lot. Even Vector has 'em! You could deal without the extra bytecodes to interpret.
But not just when the code is being run. The class file is bigger. Extra instructions, but also setting up the try/finally tables and verification that something naughty hasn't been slipped in.
Just my guess.
Are you asking why are there two ways of doing the same thing?
When a method is market as synchronized, it would be redundant to also have monitorenter/exit instructions. If it only had monitorenter/exit instruction you would not bet able to see externally that the method is synchronized (without reading the actual code)
There are more than a few examples of two or more ways of doing the same thing. Each has relative strengths and weaknesses. (e.g. many of the single byte instructions are short versions of a two byte instruction)
EDIT: I must be missing something in the question because the caller doesn't need to know if the callee is synchronized
public static void main(String... args) {
print();
printSynchronized();
printSynchronizedInternally();
}
public static void print() {
System.out.println("not synchronized");
}
public static synchronized void printSynchronized() {
System.out.println("synchronized");
}
public static void printSynchronizedInternally() {
synchronized(Class.class) {
System.out.println("synchronized internally");
}
}
produces the code
public static void main(java.lang.String[]);
Code:
0: invokestatic #2; //Method print:()V
3: invokestatic #3; //Method printSynchronized:()V
6: invokestatic #4; //Method printSynchronizedInternally:()V
9: return
public static void print();
Code:
0: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #6; //String not synchronized
5: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
public static synchronized void printSynchronized();
Code:
0: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #8; //String synchronized
5: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
public static void printSynchronizedInternally();
Code:
0: ldc_w #9; //class java/lang/Class
3: dup
4: astore_0
5: monitorenter
6: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #10; //String synchronized internally
11: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: aload_0
15: monitorexit
16: goto 24
19: astore_1
20: aload_0
21: monitorexit
22: aload_1
23: athrow
24: return
Exception table:
from to target type
6 16 19 any
19 22 19 any
}
<speculation>
By delegating lock management onto the caller, some optimizations are now possible. For example, suppose you have a class like this:
public class Foo {
public synchronized void bar() {
// ...
}
}
And suppose it is used by this caller class:
public class Caller {
public void call() {
Foo foo = new Foo();
// implicit MONITORENTER on foo's lock
foo.bar();
// implicit MONITOREXIT on foo's lock
}
}
Based on escape analysis, the JVM knows that foo never escapes the thread. Because of this, it can avoid the implicit MONITORENTER and MONITOREXIT instructions.
Avoiding unnecessary locks may have been more performance-driven in earlier days of the JVM when speed was a rare commodity.
</speculation>
Are you asking why synchronised methods use explicit monitor entry and exit instruction when the JVM could infer them by looking at the method's attributes?
I would guess it is because, as well as methods it is possible to synchronise arbitrary blocks of code:
synchronized( some_object ){ // monitorentry some_object
System.out.println("I am synchronised!");
} // monitorexit some_object
Therefore it makes sense to use the same instructions for both synchronised methods and synchronised blocks.
Was searching on the same question, and came across the following article. Looks like method level synchronization generates slightly more efficient byte code than block level synchronization. For block level synchronization, explicit byte code is generated to handle exceptions which is not done for method level synchronization. So a possible answer could be, these two ways are used to make method level synchronization slightly faster.
http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/

Categories