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
}
Related
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!
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.
When we create a final in java it is guaranteed that it cannot be changed even at run time because the JVM guarantees it.
Java class:
public class JustATest {
public final int x = 10;
}
Javap decompiled:
Compiled from "JustATest.java"
public class JustATest {
public final int x;
public JustATest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 10
7: putfield #2 // Field x:I
10: return
}
But in scala, if we declare a val, it compiles into a normal integer and there is no difference between var and val in terms of decompilation output.
Original Scala class:
class AnTest {
val x = 1
var y = 2
}
Decompiled output:
Compiled from "AnTest.scala"
public class AnTest {
public int x();
Code:
0: aload_0
1: getfield #14 // Field x:I
4: ireturn
public int y();
Code:
0: aload_0
1: getfield #18 // Field y:I
4: ireturn
public void y_$eq(int);
Code:
0: aload_0
1: iload_1
2: putfield #18 // Field y:I
5: return
public AnTest();
Code:
0: aload_0
1: invokespecial #25 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_1
6: putfield #14 // Field x:I
9: aload_0
10: iconst_2
11: putfield #18 // Field y:I
14: return
}
With that information, the concept of immutability of a val is controlled only at compile time by the scala compiler? How is this guaranteed at run time?
In Scala, conveying immutability via val is a compile time enforcement which has nothing to do with the emitted byte code. In Java, you state that when the field is final in order for it not to be reassigned, where in Scala, declaring a variable with val only means it can't be reassigned, but it can be overridden. If you want a field to be final, you'll need to specify it as you do in Java:
class AnTest {
final val x = 10
}
Which yields:
public class testing.ReadingFile$AnTest$1 {
private final int x;
public final int x();
Code:
0: bipush 10
2: ireturn
public testing.ReadingFile$AnTest$1();
Code:
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: return
}
Which is equivalent to the byte code you see in Java, except the compiler has emitted a getter for x.
The really simple answer is: there are some Scala features which can be encoded in JVM bytecode, and some which can't.
In particular, there are some constraints which cannot be encoded in JVM bytecode, e.g. sealed or private[this], or val. Which means that if you get your hands on the compiled JVM bytecode of a Scala source file, then you can do stuff that you can't do from Scala by interacting with the code through a language that is not Scala.
This is not specific to the JVM backend, you have similar, and even more pronounced problems with Scala.js, since the compilation target here (ECMAScript) offers even less ways of expressing constraints than JVM bytecode does.
But really, this is just a general problem: I can take a language as safe and pure as Haskell, compile it to native code, and if I get my hands on the compiled binary, all safety will be lost. In fact, most Haskell compilers perform (almost) complete type erasure, so there are literally no types, and no type constraints left after compilation.
Which one is more optimal or is there any difference at all?
String s = methodThatReturnsString();
int i = methodThatReturnsInt();
thirdMethod(s, i);
or
thirdMethod(methodThatReturnsString(), methodThatReturnsInt());
By optimal I mean optimal in the terms of memory usage etc.
It has nothing to do with optimization here, but it's more a question of readability of your code...
Which one is more optimal?
The one which is easier to read :-)
I would think that any difference is optimized away when compiled (provided that the declared variables are not used afterwards - i.e. the solutions are otherwise identical).
I highly suspect that both forms are identical, but don't take my word for it. Let's find out ourselves! :D
public class Tests {
public void test1() {
String s = methodThatReturnsString();
int i = methodThatReturnsInt();
thirdMethod(s, i);
}
public void test2() {
thirdMethod(methodThatReturnsString(), methodThatReturnsInt());
}
public String methodThatReturnsString() {
return "";
}
public int methodThatReturnsInt() {
return 0;
}
public void thirdMethod(String s, int i) {
}
}
Let's compile it:
> javac -version
javac 1.6.0_17
> javac Tests.java
Now, let's print out the bytecode instructions!
> javap -c Tests
Compiled from "Tests.java"
public class Tests extends java.lang.Object{
public Tests();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public void test1();
Code:
0: aload_0
1: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String;
4: astore_1
5: aload_0
6: invokevirtual #3; //Method methodThatReturnsInt:()I
9: istore_2
10: aload_0
11: aload_1
12: iload_2
13: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V
16: return
public void test2();
Code:
0: aload_0
1: aload_0
2: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String;
5: aload_0
6: invokevirtual #3; //Method methodThatReturnsInt:()I
9: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V
12: return
public java.lang.String methodThatReturnsString();
Code:
0: ldc #5; //String
2: areturn
public int methodThatReturnsInt();
Code:
0: iconst_0
1: ireturn
public void thirdMethod(java.lang.String, int);
Code:
0: return
}
I thought this looked a bit strange - test1() and test2() are different. It looks like the compiler is adding the debugging symbols. Perhaps this is forcing it to explicitly assign return values to the local variables, introducing extra instructions.
Let's try recompiling it with no debugging:
> javac -g:none Tests.java
> javap -c Tests
public class Tests extends java.lang.Object{
public Tests();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public void test1();
Code:
0: aload_0
1: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String;
4: astore_1
5: aload_0
6: invokevirtual #3; //Method methodThatReturnsInt:()I
9: istore_2
10: aload_0
11: aload_1
12: iload_2
13: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V
16: return
public void test2();
Code:
0: aload_0
1: aload_0
2: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String;
5: aload_0
6: invokevirtual #3; //Method methodThatReturnsInt:()I
9: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V
12: return
public java.lang.String methodThatReturnsString();
Code:
0: ldc #5; //String
2: areturn
public int methodThatReturnsInt();
Code:
0: iconst_0
1: ireturn
public void thirdMethod(java.lang.String, int);
Code:
0: return
}
Inconceivable!
So, according to my compiler (Sun JDK), the bytecode is shorter for the second version. However, the virtual machine will probably optimize any differences away. :)
Edit: Some extra clarification courtesy of Joachim Sauer's comment:
It's important to note that the byte
code tells only half the story: How it
is actually executed depends a lot on
the JVM (that's quite different to
C/C++, where you can see the assembler
code and it's exactly how it's
executed). I think you realize that,
but I think it should be made clearer
in the post.
I would prefer the first option. However this has nothing to do with speed, but with debuggability. In the second option I can not easily check what the values of s and i are. Performance-wise this will not make any difference at all.
There shouldn't be any difference. Both the temporarily used String and int have to reside somewhere and Java is, internally, a stack machine. So regardless of whether you give the return values of that method calls names or not, they have to be stored on the stack prior to execution of thirdMethod(String, int).
Implications of that for the resulting JITted code can be hard to find. That's on a completely different level ob abstraction.
If in doubt, profile. But I wouldn't expect any difference here.
It is the same thing. In both cases the same functions will be called and variables (automatic or explicitly defined will be allocated). The only difference is that in the second case, the variables will be ready to garbage collected whereas on the first one you need to wait to get out of scope.
Of course however the first one is much more readable.
There is no difference at all. In this case, you might want to consider readability and clearness.
Experiment and measure. If speed is what matters, measure speed. If memory usage matters, measure memory usage. If number of bytecode instructions is what matters, count bytecode instructions. If code readability is what matters, measure code readability. Figuring out how to measure code readability is your homework.
If you don't experiment and measure all you get will be opinion and argument.
Or, if you are very lucky, someone on SO will run your experiments for you.
PS This post is, of course, my opinion and argument
thirdMethod(metodThatReturnsString(), metodThatReturnsInt());
is more optimal...
This is a question that arose mostly of pure curiosity (and killing some time). I'm asking specifically about Java for the sake of concreteness.
What happens, in memory, if I concatenate a string (any string) with an empty string, e.g.:
String s = "any old string";
s += "";
I know that afterward, the contents of s will still be "any old string", since an empty ASCII string is stored in memory as just an ASCII null (since, at least in Java, strings are always null-terminated). But I am curious to know if Java (the compiler? the VM?) performs enough optimization to know that s will be unchanged, and it can just completely omit that instruction in the bytecode, or if something different happens at compile and run times.
It's bytecode time!
class EmptyString {
public static void main(String[] args) {
String s = "any old string";
s += "";
}
}
javap -c EmptyString:
Compiled from "EmptyString.java"
class EmptyString extends java.lang.Object{
EmptyString();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String any old string
2: astore_1
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."":()V
10: aload_1
11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #6; //String
16: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: return
}
You can see that += causes a StringBuilder to be created regardless of what it's concatenating, so it can't be optimized at runtime.
On the other hand, if you put both String literals in the same expression, they are concatenated by the compiler:
class EmptyString {
public static void main(String[] args) {
String s = "any old string" + "";
}
}
javap -c EmptyString:
Compiled from "EmptyString.java"
class EmptyString extends java.lang.Object{
EmptyString();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String any old string
2: astore_1
3: return
}
You'll get a new String after executing the line
s += "";
Java allocates a new String object and assigns it to s after the string concatenation. If you have eclipse handy (and I assume you can do the same thing in NetBeans, but I've only ever used eclipse) you can breakpoint that line and watch the object IDs of the object that s points to before and after executing that line. In my case, the object ID of s before that line of code was id=20, and afterward was id=24.