Сбой актеров Akka, ошибка проверки: несогласованные кадры стековой карты в целевой ветви

#java #akka #verifyerror #try-with-resources #typedactor

#java #akka #ошибка проверки #попытка с ресурсами #typedactor

Вопрос:

У меня есть Java-приложение, в котором я использую актеров, типизированных Akka. В коде Eclipse нет ошибок, но при запуске моего приложения происходит сбой и выводится эта ошибка:

 Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 266 in method com.example.actors.DBActor.getItems(Lorg/joda/time/DateTime;Lorg/joda/time/DateTime;)I at offset 170
    at com.example.ui.Main$1.create(Main.java:31)
    at akka.actor.TypedActor$$anonfun$newInstance$3.apply(TypedActor.scala:677)
    at akka.actor.TypedActor$$anonfun$newInstance$3.apply(TypedActor.scala:677)
    at akka.actor.TypedActor$.newTypedActor(TypedActor.scala:847)
    at akka.actor.TypedActor$$anonfun$newInstance$1.apply(TypedActor.scala:601)
    at akka.actor.TypedActor$$anonfun$newInstance$1.apply(TypedActor.scala:601)
    at akka.actor.LocalActorRef.akka$actor$LocalActorRef$$newActor(ActorRef.scala:1084)
    at akka.actor.LocalActorRef$$anonfun$2.apply(ActorRef.scala:628)
    at akka.actor.LocalActorRef$$anonfun$2.apply(ActorRef.scala:628)
    at akka.util.ReentrantGuard.withGuard(LockUtil.scala:20)
    at akka.actor.LocalActorRef.<init>(ActorRef.scala:628)
    at akka.actor.Actor$.actorOf(Actor.scala:249)
    at akka.actor.TypedActor$.newInstance(TypedActor.scala:677)
    at akka.actor.TypedActor.newInstance(TypedActor.scala)
    at com.example.ui.Main.main(Main.java:29)
  

Я не понимаю, что может быть не так. Я проверил свой com.example.actors.DBActor.getItems() , но в нем нет ошибки. Что может быть не так?


Обновить

Ниже приведен пример кода, в котором я получаю эту ошибку. У меня есть эти jar-файлы в «пути сборки» в Eclipse:

  • derby.jar (из JDK7) (в этом примере используется только база данных в памяти)
  • akka-actor-1.2.jar
  • akka-typed-actor-1.2.jar
  • aspectwerkz-2.2.3.jar
  • scala-library.jar

Вот код:

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import akka.actor.TypedActor;
import akka.actor.TypedActorFactory;


public class App {

    public App() {
        TypedActor.newInstance(Backend.class, new TypedActorFactory() {
            public TypedActor create() {
                return new DataActor();
            }
        });
    }

    class DataActor extends TypedActor implements Backend {

        @Override
        public void insertData(String msg) {
            final String sqlSelect = "SELECT msg FROM SESSION.messages " 
                                     "WHERE to_user_id = ? AND from_user_id = ?";
            final String connectionURL = "jdbc:derby:memory:memdatabase;create=true";

            /* if this declaration is moved to where the string is used 
               in the conditional, the conditional can be used */
            String resu<

            try(Connection conn = DriverManager.getConnection(connectionURL);) {

                try(PreparedStatement ps = conn.prepareStatement(sqlSelect);
                    ResultSet rs = new QueryHelper(ps)
                                    .integer(13).integer(26).executeQuery();) {

                    /* this doesn't work */

                    result = (rs.next()) ? rs.getString("text")
                                         : null;

                    /* but this work:

                     String result = (rs.next()) ? rs.getString("text")
                                                 : null;
                     */

                    /* this works fine 

                    while(rs.next()) {
                        result = rs.getString("msg");
                    }                                   */
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    class QueryHelper {
        private final PreparedStatement ps;
        private int index = 1;

        public QueryHelper(PreparedStatement ps) {
            this.ps = ps;
        }

        public QueryHelper integer(int param) throws SQLException {
            ps.setInt(index  , param);
            return this;
        }

        public ResultSet executeQuery() throws SQLException {
            return ps.executeQuery();
        }
    }

    public interface Backend {
        public void insertData(String text);
    }

    public static void main(String[] args) {
        new App();
    }
}
  

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

1. Это может произойти, когда сгенерированный байтовым кодом код собран неправильно. Я бы попробовал более раннюю версию (или более позднюю версию)

2. @Peter: У меня был более ранний выпуск, но я получил ту же ошибку, но другим методом.

3. TypedActors в Akka < 2.0 использует ткачество байт-кода AspektWerkz, я понятия не имею, что может быть причиной вашей проблемы, но если вы можете минимизировать проблему и отправить заявку, кто-нибудь мог бы взглянуть на это.

4. @ViktorKlang: Может быть, я использую Java 7? Я попытаюсь создать минимальную программу.

5. Я видел ошибку с другим усилителем байтового кода / модификациями при запуске на Java 7. Решением было явно скомпилировать код для Java 6: -target 1.6 в javac.

Ответ №1:

Я обнаружил, что эта ошибка возникает в местах, где я использую несколько ресурсов в одной инструкции Java 7 try-with-resources.

Например, в этом коде будет ошибка:

 try (Connection conn = DriverManager.getConnection(connURL);
     PreparedStatement ps = conn.prepareStatement(sql);) {

    // do something

} catch (SQLException e) {
    e.printStackTrace();
}
  

и обходной путь будет выглядеть следующим образом:

 try (Connection conn = DriverManager.getConnection(connURL);) {
    try (PreparedStatement ps = conn.prepareStatement(sql);) {

        // do something

    }
} catch (SQLException e) {
    e.printStackTrace();
}
  

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

1. Я никогда не видел попытки с parameters ()

Ответ №2:

запустите java с опцией -XX:-UseSplitVerifier

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

1. «Предупреждение 64-разрядной виртуальной машины сервера OpenJDK: игнорируется параметр UseSplitVerifier; поддержка была удалена в версии 8.0»