Почему отладчик Intellij дважды достигает точки останова для этого кода Scala

#java #scala #debugging #intellij-idea #breakpoints

#Ява #scala #отладка #intellij-идея #точки останова

Вопрос:

Для следующего кода scala, когда я устанавливаю точку отладки в операторе if и включаю «Журнал: сообщение о достижении точки останова».

 object App1 {  def main(args: Array[String]): Unit = {  iftest()  }  def iftest(): Unit = {  val setA: Set[String] = Set("a", "b", "c");  var setB: Set[String] = Set("d", "e", "f")  if(setA.size gt; setB.size){ //here break point at line 8  println("bigger")  }  } }  

Я получил следующий вывод в консоли. Вопрос в том, почему эта точка останова поражается дважды?

 Breakpoint reached at com.eguller.App1$.iftest(App1.scala:8) Breakpoint reached at com.eguller.App1$.iftest(App1.scala:8)  

Но для выполнения аналогичного кода Java точка останова задается только один раз.

 Setlt;Stringgt; set1 = new HashSetlt;gt;();  set1.add("1");  set1.add("2");   Setlt;Stringgt; set2 = new HashSetlt;gt;();  set2.add("a");  set2.add("b");   if(set1.size() gt; set2.size()){ //here break point at line 8  System.out.println("size different");  }  

Я получил следующий результат

 Breakpoint reached at com.eguller.JApp.main(JApp.java:8)  

Это ошибка в отладчике Intellij или это особенность языка программирования Scala?

IntelliJ IDEA 2021.3 Java — 11 Scala — 2.12.15

Ответ №1:

Это особенность генерации байт-кода scalac. По какой-то причине он создает дополнительную позицию для отладчика непосредственно перед инструкцией возврата и помещает ее в эту строку. Вы можете вызвать действие «Показать байт-код» в среде IDE и увидеть, что есть 2 LINENUMBER 8 записи:

 // access flags 0x1 public iftest()V  L0  LINENUMBER 6 L0  GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$;  INVOKEVIRTUAL scala/Predef$.Set ()Lscala/collection/immutable/Set$;  GETSTATIC scala/runtime/ScalaRunTime$.MODULE$ : Lscala/runtime/ScalaRunTime$;  ICONST_3  ANEWARRAY java/lang/String  DUP  ICONST_0  LDC "a"  AASTORE  DUP  ICONST_1  LDC "b"  AASTORE  DUP  ICONST_2  LDC "c"  AASTORE  CHECKCAST [Ljava/lang/Object;  INVOKEVIRTUAL scala/runtime/ScalaRunTime$.wrapRefArray ([Ljava/lang/Object;)Lscala/collection/immutable/ArraySeq;  INVOKEVIRTUAL scala/collection/immutable/Set$.apply (Lscala/collection/immutable/Seq;)Ljava/lang/Object;  CHECKCAST scala/collection/immutable/Set  ASTORE 1  L1  LINENUMBER 7 L1  GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$;  INVOKEVIRTUAL scala/Predef$.Set ()Lscala/collection/immutable/Set$;  GETSTATIC scala/runtime/ScalaRunTime$.MODULE$ : Lscala/runtime/ScalaRunTime$;  ICONST_3  ANEWARRAY java/lang/String  DUP  ICONST_0  LDC "d"  AASTORE  DUP  ICONST_1  LDC "e"  AASTORE  DUP  ICONST_2  LDC "f"  AASTORE  CHECKCAST [Ljava/lang/Object;  INVOKEVIRTUAL scala/runtime/ScalaRunTime$.wrapRefArray ([Ljava/lang/Object;)Lscala/collection/immutable/ArraySeq;  INVOKEVIRTUAL scala/collection/immutable/Set$.apply (Lscala/collection/immutable/Seq;)Ljava/lang/Object;  CHECKCAST scala/collection/immutable/Set  ASTORE 2  L2  LINENUMBER 8 L2  ALOAD 1  INVOKEINTERFACE scala/collection/immutable/Set.size ()I (itf)  ALOAD 2  INVOKEINTERFACE scala/collection/immutable/Set.size ()I (itf)  IF_ICMPLE L3  L4  LINENUMBER 9 L4  GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$;  LDC "bigger"  INVOKEVIRTUAL scala/Predef$.println (Ljava/lang/Object;)V  GOTO L3  L3  LINENUMBER 8 L3  FRAME APPEND [scala/collection/immutable/Set scala/collection/immutable/Set]  RETURN  L5  LOCALVARIABLE setA Lscala/collection/immutable/Set; L1 L3 1  LOCALVARIABLE setB Lscala/collection/immutable/Set; L2 L3 2  LOCALVARIABLE this LApp1$; L0 L5 0  MAXSTACK = 6  MAXLOCALS = 3  

Компилятор Scala 3 этого не добавляет, и точки останова работают должным образом.

Комментарии:

1. Спасибо @niktrop, я отлаживал код Scala, в котором есть для понимания/доходности, фьючерсы и т.д. Я подумал, что мой код вызывается дважды, и попытался выяснить первопричину. В конце концов, я подозреваю, что, возможно, код не выполняется дважды, но точка останова попадает несколько раз и проверяется простым методом. И действительно, так оно и было.