Why use javap -v on a special class to generate a output, in the output, i can't find the nested method bytecode


#1

after i scalac the follow code, i get servel class file.
the test code:

// HightOrder.scala
object SalaryRaiser {

  private def promotion(salaries: List[Double], promotionFunction: Double => Double): List[Double] =
    salaries.map(promotionFunction)

  def smallPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * 1.1)

  def bigPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * math.log(salary))

  def hugePromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * salary)

  def factorial(x: Int): Int = {
     /* here is the nested method */
    def fact(x: Int, accumulator: Int): Int = {
      if (x <= 1) accumulator
      else fact(x - 1, x * accumulator)
    }
    fact(x, 1)
  }
}

object SalaryRaiserTest extends App {

  val salaries = Seq(20000, 70000, 40000)
  val doubleSalary = (x: Int) => x * 2
  val newSalaries = salaries.map(doubleSalary)

  println(newSalaries)
  println("Factorial of 2: " + SalaryRaiser.factorial(2))
  println("Factorial of 3: " + SalaryRaiser.factorial(3))
}

class file:

see@17:28:30 scala-tour  ll *.class
-rw-rw-r--. 1 see see 1.3K May 16 17:23 SalaryRaiser.class
-rw-rw-r--. 1 see see 3.4K May 16 17:23 SalaryRaiser$.class
-rw-rw-r--. 1 see see 1.5K May 16 17:23 SalaryRaiserTest.class
-rw-rw-r--. 1 see see 5.0K May 16 17:23 SalaryRaiserTest$.class
-rw-rw-r--. 1 see see  833 May 16 17:23 SalaryRaiserTest$delayedInit$body.class

the i use:

javap -v SalaryRaiser.class > SalaryRaiser.p 
javap -v SalaryRaiser\$.class > SalaryRaiser\$.p

i can only find the nested method in constant pool, but where is the method bytecode?

my enviroment is:

scala-2.12.6-1.noarch

openjdk version "1.8.0_161"
OpenJDK Runtime Environment (build 1.8.0_161-b14)
OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode) 

#2

the full output of SalaryRaiser$.p

Classfile /home/see/work/container/play/scala-tour/SalaryRaiser$.class
  Last modified May 16, 2018; size 3381 bytes
  MD5 checksum a2cada09454f343e93b379b70d39c273
  Compiled from "HightOrder.scala"
public final class SalaryRaiser$
  BootstrapMethods:
    0: #48 invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
      Method arguments:
        #50 (D)D
        #54 invokestatic SalaryRaiser$.$anonfun$smallPromotion$1:(D)D
        #50 (D)D
        #55 3
        #56 1
        #58 scala/Serializable
    1: #48 invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
      Method arguments:
        #50 (D)D
        #69 invokestatic SalaryRaiser$.$anonfun$bigPromotion$1:(D)D
        #50 (D)D
        #55 3
        #56 1
        #58 scala/Serializable
    2: #48 invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
      Method arguments:
        #50 (D)D
        #75 invokestatic SalaryRaiser$.$anonfun$hugePromotion$1:(D)D
        #50 (D)D
        #55 3
        #56 1
        #58 scala/Serializable
    3: #109 invokestatic scala/runtime/LambdaDeserialize.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
      Method arguments:
        #54 invokestatic SalaryRaiser$.$anonfun$smallPromotion$1:(D)D
        #69 invokestatic SalaryRaiser$.$anonfun$bigPromotion$1:(D)D
        #75 invokestatic SalaryRaiser$.$anonfun$hugePromotion$1:(D)D
  SourceFile: "HightOrder.scala"
  InnerClasses:
       public static final #10= #7 of #9; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
    ScalaInlineInfo: length = 0x36
     01 01 00 0A 00 42 00 31 01 00 48 00 31 01 00 33
     00 31 01 00 0F 00 0E 01 00 41 00 29 01 00 50 00
     51 01 00 4D 00 4E 01 00 47 00 29 01 00 12 00 13
     01 00 28 00 29 01
    Scala: length = 0x0

  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
    #1 = Utf8               SalaryRaiser$
    #2 = Class              #1            //  SalaryRaiser$
    #3 = Utf8               java/lang/Object
    #4 = Class              #3            //  java/lang/Object
    #5 = Utf8               HightOrder.scala
    #6 = Utf8               java/lang/invoke/MethodHandles$Lookup
    #7 = Class              #6            //  java/lang/invoke/MethodHandles$Lookup
    #8 = Utf8               java/lang/invoke/MethodHandles
    #9 = Class              #8            //  java/lang/invoke/MethodHandles
   #10 = Utf8               Lookup
   #11 = Utf8               MODULE$
   #12 = Utf8               LSalaryRaiser$;
   #13 = Utf8               <clinit>
   #14 = Utf8               ()V
   #15 = Utf8               <init>
   #16 = NameAndType        #15:#14       //  "<init>":()V
   #17 = Methodref          #2.#16        //  SalaryRaiser$."<init>":()V
   #18 = Utf8               promotion
   #19 = Utf8               (Lscala/collection/immutable/List;Lscala/Function1;)Lscala/collection/immutable/List;
   #20 = Utf8               salaries
   #21 = Utf8               promotionFunction
   #22 = Utf8               scala/collection/immutable/List$
   #23 = Class              #22           //  scala/collection/immutable/List$
   #24 = Utf8               Lscala/collection/immutable/List$;
   #25 = NameAndType        #11:#24       //  MODULE$:Lscala/collection/immutable/List$;
   #26 = Fieldref           #23.#25       //  scala/collection/immutable/List$.MODULE$:Lscala/collection/immutable/List$;
   #27 = Utf8               canBuildFrom
   #28 = Utf8               ()Lscala/collection/generic/CanBuildFrom;
   #29 = NameAndType        #27:#28       //  canBuildFrom:()Lscala/collection/generic/CanBuildFrom;
   #30 = Methodref          #23.#29       //  scala/collection/immutable/List$.canBuildFrom:()Lscala/collection/generic/CanBuildFrom;
   #31 = Utf8               scala/collection/immutable/List
   #32 = Class              #31           //  scala/collection/immutable/List
   #33 = Utf8               map
   #34 = Utf8               (Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;
   #35 = NameAndType        #33:#34       //  map:(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;
   #36 = Methodref          #32.#35       //  scala/collection/immutable/List.map:(Lscala/Function1;Lscala/collection/generic/CanBuildFrom;)Ljava/lang/Object;
   #37 = Utf8               this
   #38 = Utf8               Lscala/collection/immutable/List;
   #39 = Utf8               Lscala/Function1;
   #40 = Utf8               smallPromotion
   #41 = Utf8               (Lscala/collection/immutable/List;)Lscala/collection/immutable/List;
   #42 = Utf8               java/lang/invoke/LambdaMetafactory
   #43 = Class              #42           //  java/lang/invoke/LambdaMetafactory
   #44 = Utf8               altMetafactory
   #45 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
   #46 = NameAndType        #44:#45       //  altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
   #47 = Methodref          #43.#46       //  java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
   #48 = MethodHandle       #6:#47        //  invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
   #49 = Utf8               (D)D
   #50 = MethodType         #49           //  (D)D
   #51 = Utf8               $anonfun$smallPromotion$1
   #52 = NameAndType        #51:#49       //  $anonfun$smallPromotion$1:(D)D
   #53 = Methodref          #2.#52        //  SalaryRaiser$.$anonfun$smallPromotion$1:(D)D
   #54 = MethodHandle       #6:#53        //  invokestatic SalaryRaiser$.$anonfun$smallPromotion$1:(D)D
   #55 = Integer            3
   #56 = Integer            1
   #57 = Utf8               scala/Serializable
   #58 = Class              #57           //  scala/Serializable
   #59 = Utf8               apply$mcDD$sp
   #60 = Utf8               ()Lscala/runtime/java8/JFunction1$mcDD$sp;
   #61 = NameAndType        #59:#60       //  apply$mcDD$sp:()Lscala/runtime/java8/JFunction1$mcDD$sp;
   #62 = InvokeDynamic      #0:#61        //  #0:apply$mcDD$sp:()Lscala/runtime/java8/JFunction1$mcDD$sp;
   #63 = NameAndType        #18:#19       //  promotion:(Lscala/collection/immutable/List;Lscala/Function1;)Lscala/collection/immutable/List;
   #64 = Methodref          #2.#63        //  SalaryRaiser$.promotion:(Lscala/collection/immutable/List;Lscala/Function1;)Lscala/collection/immutable/List;
   #65 = Utf8               bigPromotion
   #66 = Utf8               $anonfun$bigPromotion$1
   #67 = NameAndType        #66:#49       //  $anonfun$bigPromotion$1:(D)D
   #68 = Methodref          #2.#67        //  SalaryRaiser$.$anonfun$bigPromotion$1:(D)D
   #69 = MethodHandle       #6:#68        //  invokestatic SalaryRaiser$.$anonfun$bigPromotion$1:(D)D
   #70 = InvokeDynamic      #1:#61        //  #1:apply$mcDD$sp:()Lscala/runtime/java8/JFunction1$mcDD$sp;
   #71 = Utf8               hugePromotion
   #72 = Utf8               $anonfun$hugePromotion$1
   #73 = NameAndType        #72:#49       //  $anonfun$hugePromotion$1:(D)D
   #74 = Methodref          #2.#73        //  SalaryRaiser$.$anonfun$hugePromotion$1:(D)D
   #75 = MethodHandle       #6:#74        //  invokestatic SalaryRaiser$.$anonfun$hugePromotion$1:(D)D
   #76 = InvokeDynamic      #2:#61        //  #2:apply$mcDD$sp:()Lscala/runtime/java8/JFunction1$mcDD$sp;
   #77 = Utf8               factorial
   #78 = Utf8               (I)I
   #79 = Utf8               x
   #80 = Utf8               fact$1
   #81 = Utf8               (II)I
   #82 = NameAndType        #80:#81       //  fact$1:(II)I
   #83 = Methodref          #2.#82        //  SalaryRaiser$.fact$1:(II)I
   #84 = Utf8               I
   #85 = Utf8               salary
   #86 = Double             1.1d
   #88 = Utf8               D
   #89 = Utf8               scala/math/package$
   #90 = Class              #89           //  scala/math/package$
   #91 = Utf8               Lscala/math/package$;
   #92 = NameAndType        #11:#91       //  MODULE$:Lscala/math/package$;
   #93 = Fieldref           #90.#92       //  scala/math/package$.MODULE$:Lscala/math/package$;
   #94 = Utf8               log
   #95 = NameAndType        #94:#49       //  log:(D)D
   #96 = Methodref          #90.#95       //  scala/math/package$.log:(D)D
   #97 = Utf8               accumulator
   #98 = Methodref          #4.#16        //  java/lang/Object."<init>":()V
   #99 = NameAndType        #11:#12       //  MODULE$:LSalaryRaiser$;
  #100 = Fieldref           #2.#99        //  SalaryRaiser$.MODULE$:LSalaryRaiser$;
  #101 = Utf8               $deserializeLambda$
  #102 = Utf8               (Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;
  #103 = Utf8               scala/runtime/LambdaDeserialize
  #104 = Class              #103          //  scala/runtime/LambdaDeserialize
  #105 = Utf8               bootstrap
  #106 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
  #107 = NameAndType        #105:#106     //  bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
  #108 = Methodref          #104.#107     //  scala/runtime/LambdaDeserialize.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
  #109 = MethodHandle       #6:#108       //  invokestatic scala/runtime/LambdaDeserialize.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
  #110 = Utf8               lambdaDeserialize
  #111 = NameAndType        #110:#102     //  lambdaDeserialize:(Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;
  #112 = InvokeDynamic      #3:#111       //  #3:lambdaDeserialize:(Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;
  #113 = Utf8               Code
  #114 = Utf8               LocalVariableTable
  #115 = Utf8               LineNumberTable
  #116 = Utf8               Signature
  #117 = Utf8               (Lscala/collection/immutable/List<Ljava/lang/Object;>;Lscala/Function1<Ljava/lang/Object;Ljava/lang/Object;>;)Lscala/collection/immutable/List<Ljava/lang/Object;>;
  #118 = Utf8               MethodParameters
  #119 = Utf8               (Lscala/collection/immutable/List<Ljava/lang/Object;>;)Lscala/collection/immutable/List<Ljava/lang/Object;>;
  #120 = Utf8               StackMapTable
  #121 = Utf8               BootstrapMethods
  #122 = Utf8               SourceFile
  #123 = Utf8               InnerClasses
  #124 = Utf8               ScalaInlineInfo
  #125 = Utf8               Scala
{
  public static SalaryRaiser$ MODULE$;
    flags: ACC_PUBLIC, ACC_STATIC

  public static {};
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: new           #2                  // class SalaryRaiser$
         3: invokespecial #17                 // Method "<init>":()V
         6: return

  public scala.collection.immutable.List<java.lang.Object> smallPromotion(scala.collection.immutable.List<java.lang.Object>);
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: invokedynamic #62,  0             // InvokeDynamic #0:apply$mcDD$sp:()Lscala/runtime/java8/JFunction1$mcDD$sp;
         7: invokespecial #64                 // Method promotion:(Lscala/collection/immutable/List;Lscala/Function1;)Lscala/collection/immutable/List;
        10: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      11     0  this   LSalaryRaiser$;
               0      11     1 salaries   Lscala/collection/immutable/List;
      LineNumberTable:
        line 8: 0
    Signature: #119                         // (Lscala/collection/immutable/List<Ljava/lang/Object;>;)Lscala/collection/immutable/List<Ljava/lang/Object;>;
      MethodParameters: length = 0x5
       01 00 14 00 10

  public scala.collection.immutable.List<java.lang.Object> bigPromotion(scala.collection.immutable.List<java.lang.Object>);
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: invokedynamic #70,  0             // InvokeDynamic #1:apply$mcDD$sp:()Lscala/runtime/java8/JFunction1$mcDD$sp;
         7: invokespecial #64                 // Method promotion:(Lscala/collection/immutable/List;Lscala/Function1;)Lscala/collection/immutable/List;
        10: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      11     0  this   LSalaryRaiser$;
               0      11     1 salaries   Lscala/collection/immutable/List;
      LineNumberTable:
        line 11: 0
    Signature: #119                         // (Lscala/collection/immutable/List<Ljava/lang/Object;>;)Lscala/collection/immutable/List<Ljava/lang/Object;>;
      MethodParameters: length = 0x5
       01 00 14 00 10

  public scala.collection.immutable.List<java.lang.Object> hugePromotion(scala.collection.immutable.List<java.lang.Object>);
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: invokedynamic #76,  0             // InvokeDynamic #2:apply$mcDD$sp:()Lscala/runtime/java8/JFunction1$mcDD$sp;
         7: invokespecial #64                 // Method promotion:(Lscala/collection/immutable/List;Lscala/Function1;)Lscala/collection/immutable/List;
        10: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      11     0  this   LSalaryRaiser$;
               0      11     1 salaries   Lscala/collection/immutable/List;
      LineNumberTable:
        line 14: 0
    Signature: #119                         // (Lscala/collection/immutable/List<Ljava/lang/Object;>;)Lscala/collection/immutable/List<Ljava/lang/Object;>;
      MethodParameters: length = 0x5
       01 00 14 00 10

  public int factorial(int);
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0
         1: iload_1
         2: iconst_1
         3: invokespecial #83                 // Method fact$1:(II)I
         6: ireturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       7     0  this   LSalaryRaiser$;
               0       7     1     x   I
      LineNumberTable:
        line 21: 0
      MethodParameters: length = 0x5
       01 00 4F 00 10

  public static final double $anonfun$smallPromotion$1(double);
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
    Code:
      stack=4, locals=2, args_size=1
         0: dload_0
         1: ldc2_w        #86                 // double 1.1d
         4: dmul
         5: dreturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       6     0 salary   D
      LineNumberTable:
        line 8: 0
      MethodParameters: length = 0x5
       01 00 55 00 10

  public static final double $anonfun$bigPromotion$1(double);
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
    Code:
      stack=5, locals=2, args_size=1
         0: dload_0
         1: getstatic     #93                 // Field scala/math/package$.MODULE$:Lscala/math/package$;
         4: dload_0
         5: invokevirtual #96                 // Method scala/math/package$.log:(D)D
         8: dmul
         9: dreturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      10     0 salary   D
      LineNumberTable:
        line 11: 0
      MethodParameters: length = 0x5
       01 00 55 00 10

  public static final double $anonfun$hugePromotion$1(double);
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
    Code:
      stack=4, locals=2, args_size=1
         0: dload_0
         1: dload_0
         2: dmul
         3: dreturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       4     0 salary   D
      LineNumberTable:
        line 14: 0
      MethodParameters: length = 0x5
       01 00 55 00 10
}

#3
scala> :pa
// Entering paste mode (ctrl-D to finish)

object SalaryRaiser {

  private def promotion(salaries: List[Double], promotionFunction: Double => Double): List[Double] =
    salaries.map(promotionFunction)

  def smallPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * 1.1)

  def bigPromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * math.log(salary))

  def hugePromotion(salaries: List[Double]): List[Double] =
    promotion(salaries, salary => salary * salary)

  def factorial(x: Int): Int = {
     /* here is the nested method */
    def fact(x: Int, accumulator: Int): Int = {
      if (x <= 1) accumulator
      else fact(x - 1, x * accumulator)
    }
    fact(x, 1)
  }
}

// Exiting paste mode, now interpreting.

defined object SalaryRaiser

then

scala> :javap -pv SalaryRaiser#fact$1
  private final int fact$1(int, int);
    descriptor: (II)I
    flags: ACC_PRIVATE, ACC_FINAL
    Code:
      stack=3, locals=3, args_size=3
         0: iload_1
         1: iconst_1
         2: if_icmpgt     9
         5: iload_2
         6: goto          20
         9: iload_1
        10: iconst_1
        11: isub
        12: iload_1
        13: iload_2
        14: imul
        15: istore_2
        16: istore_1
        17: goto          0
        20: ireturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      21     0  this   L$line4/$read$$iw$$iw$SalaryRaiser$;
            0      21     1     x   I
            0      21     2 accumulator   I
      LineNumberTable:
        line 28: 0
        line 29: 9
      StackMapTable: number_of_entries = 3
        frame_type = 0 /* same */
        frame_type = 8 /* same */
        frame_type = 74 /* same_locals_1_stack_item */
          stack = [ int ]
    MethodParameters:
      Name                           Flags
      x                              final
      accumulator                    final

scala> :javap -help
usage       :javap [opts] [path or class or -]...
-help       Prints this help message
-verbose/-v Stack size, number of locals, method args
-private/-p Private classes and members
-package    Package-private classes and members
-protected  Protected classes and members
-public     Public classes and members
-l          Line and local variable tables
-c          Disassembled code
-s          Internal type signatures
-sysinfo    System info of class
-constants  Static final constants
-filter     Filter REPL machinery from output

scala>

#4

Thank you!