Last active
February 18, 2022 13:49
-
-
Save cb372/dc0753567ae53f49d78d2e34fe25ea75 to your computer and use it in GitHub Desktop.
Explaining default args using javap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.time.Instant | |
| object Foo { | |
| case class Timers( | |
| timer1: Long, | |
| timer2: Long = Instant.now().toEpochMilli, | |
| timer3: Long | |
| ) | |
| val a = Timers( | |
| timer1 = Instant.now().toEpochMilli, | |
| timer3 = Instant.now().toEpochMilli | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $ javap -c 'Foo$.class' | |
| Compiled from "Foo.scala" | |
| public final class Foo$ { | |
| public static final Foo$ MODULE$; | |
| public static {}; | |
| Code: | |
| 0: new #2 // class Foo$ | |
| 3: dup | |
| 4: invokespecial #22 // Method "<init>":()V | |
| 7: putstatic #24 // Field MODULE$:LFoo$; | |
| 10: invokestatic #30 // Method java/time/Instant.now:()Ljava/time/Instant; | |
| 13: invokevirtual #34 // Method java/time/Instant.toEpochMilli:()J | |
| 16: lstore_0 | |
| 17: invokestatic #30 // Method java/time/Instant.now:()Ljava/time/Instant; | |
| 20: invokevirtual #34 // Method java/time/Instant.toEpochMilli:()J | |
| 23: lstore_2 | |
| 24: getstatic #37 // Field Foo$Timers$.MODULE$:LFoo$Timers$; | |
| 27: invokevirtual #40 // Method Foo$Timers$.apply$default$2:()J | |
| 30: lstore 4 | |
| 32: new #7 // class Foo$Timers | |
| 35: dup | |
| 36: lload_0 | |
| 37: lload 4 | |
| 39: lload_2 | |
| 40: invokespecial #43 // Method Foo$Timers."<init>":(JJJ)V | |
| 43: putstatic #45 // Field a:LFoo$Timers; | |
| 46: return | |
| public Foo$Timers a(); | |
| Code: | |
| 0: getstatic #45 // Field a:LFoo$Timers; | |
| 3: areturn | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $ javap -c 'Foo$Timers$.class' | |
| Compiled from "Foo.scala" | |
| public class Foo$Timers$ extends scala.runtime.AbstractFunction3<java.lang.Object, java.lang.Object, java.lang.Object, Foo$Timers> implements java.io.Serializable { | |
| public static final Foo$Timers$ MODULE$; | |
| ... | |
| public long apply$default$2(); | |
| Code: | |
| 0: invokestatic #31 // Method java/time/Instant.now:()Ljava/time/Instant; | |
| 3: invokevirtual #34 // Method java/time/Instant.toEpochMilli:()J | |
| 6: lreturn | |
| ... | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
val ais initialized when theFoo$class is loaded, in thepublic static {}method. This method does the following:invokestatic+invokevirtual) callInstant.now().toEpochMillilstore_0) save the resultinglongto local variable 0 (it will use it later as the first argument to theTimersconstructor)invokestatic+invokevirtual) callInstant.now().toEpochMilliagainlstore_2) save the result to local variable 2 (it will use it later as the third argument to the constructor)getstatic+invokevirtual) callFoo$Timers$.apply$default$2(which in turn callsInstant.now().toEpochMilliand returns the result)lstore 4) save the result to local variable 4 (it will use it later as the second argument to the constructor)new+dup) create a new (uninitialized)Timersinstancelload_0) push local variable 0 onto the stack for use as the first argument to theTimersconstructorlload 4) push local variable 4 onto the stack for use as the second argumentlload_2) push local variable 2 onto the stack for use as the third argumentinvokespecial) call theTimersconstructor, which pops the 3 args off the stackputstatic) save theTimersinstance to the fieldaSo in summary,
Instant.now.toEpochMilliis called 3 times, once for each constructor arg, so the values could all be different.