#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, в котором есть для понимания/доходности, фьючерсы и т.д. Я подумал, что мой код вызывается дважды, и попытался выяснить первопричину. В конце концов, я подозреваю, что, возможно, код не выполняется дважды, но точка останова попадает несколько раз и проверяется простым методом. И действительно, так оно и было.