Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / guava UncheckedExecutionException / 14 сообщений из 14, страница 1 из 1
21.12.2016, 11:30
    #39371707
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
WARNING: Exception thrown by removal listener
com.google.common.util.concurrent.UncheckedExecutionException: java.lang.NullPointerException
        at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2207)
        at com.google.common.cache.LocalCache.get(LocalCache.java:3953)
        at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4790)
        at main.DB.writeUserDownloadLater(DB.java:116)
        at main.cache.Session.close(Session.java:137)
        at main.DownloadMeter.lambda$main$0(DownloadMeter.java:67)
        at com.google.common.cache.LocalCache.processPendingNotifications(LocalCache.java:1960)
        at com.google.common.cache.LocalCache$Segment.runUnlockedCleanup(LocalCache.java:3475)
        at com.google.common.cache.LocalCache$Segment.postWriteCleanup(LocalCache.java:3451)
        at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2277)
        at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2201)
        at com.google.common.cache.LocalCache.get(LocalCache.java:3953)
        at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4790)
        at main.DownloadMeter.main(DownloadMeter.java:137)
Caused by: java.lang.NullPointerException
        at com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5268)
        at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5151)
        at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5190)
        at main.DB.lambda$writeUserDownloadLater$0(DB.java:127)
        at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:4793)
        at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3542)
        at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2323)
        at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2286)
        at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2201)
        ... 13 more

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
sessions = CacheBuilder
        .newBuilder()
        .initialCapacity(30000)
        .maximumSize(5000000)
        .expireAfterAccess(session_ttl, TimeUnit.SECONDS)
        .removalListener((RemovalListener<String, Session>) notification -> {
            Session session = notification.getValue();
            if (session != null) {
                logger.debug("Close session: " + notification.getKey());
                // ------------- > line 67
                session.close();
            }
        })
        .build();

...
...

//  ------------- > line 137
Session session = sessions.get(jsonMessage.get("id").getAsString(), () -> new Session(

));



Пока один поток закрывает сессию, другому потоку она понадобилась, если я все правильно понимаю.
И как такое решается?
...
Рейтинг: 0 / 0
21.12.2016, 11:38
    #39371719
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
writeUserDownloadLater не вижу в коде.
...
Рейтинг: 0 / 0
21.12.2016, 12:00
    #39371751
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Что-то я туда не догадался загнянуть, а там тоже работа с кэшем:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
public class DB {
    ...
    private static Cache<String, String> downloadsWithUserFileRelations = CacheBuilder
            .newBuilder()
            .maximumSize(1000000)
            .expireAfterAccess(15, TimeUnit.MINUTES)
            .build();
    ...
    ...
    public void writeUserDownloadLater(Session session) {
        try {
            // ------------ > line 116
            String user_file_id = downloadsWithUserFileRelations.get(session.getId(), () -> {
                downloadToUserFileStmt.setString(1, session.getId());
                ResultSet resultSet = downloadToUserFileStmt.executeQuery();
                if (!resultSet.next()) {
                    return null;
                }
                return resultSet.getString("user_file_id");
            });

            ...
            ...
        } catch (ExecutionException e) {
            DownloadMeter.logger.error("Execution exception", e);
        }
    }
}



Т.е. в removal listener был запрос к кэшу как раз, ну и я кажется понял суть проблемы.
...
Рейтинг: 0 / 0
21.12.2016, 12:02
    #39371756
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Т.е. тут NullPointerException вылетело, потому что session уже деинициализирована?
...
Рейтинг: 0 / 0
21.12.2016, 12:10
    #39371763
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Исключение всегда одно и то же? JDBC Connection случайно между потоками не шарится? Какая версия драйвера?
...
Рейтинг: 0 / 0
21.12.2016, 12:12
    #39371767
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
HettТ.е. тут NullPointerException вылетело, потому что session уже деинициализирована?
NPE вылетел в ResultSet драйвера MySQL. Где-то косяк работы с JDBC. Session к этому прямого отношения не имеет.
Как создаются и используются downloadToUserFileStmt и его Connection из указанного кода не видно.
...
Рейтинг: 0 / 0
21.12.2016, 13:13
    #39371860
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Подключение к БД одно, downloadToUserFileStmt - создается после коннекта к БД.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
testCompileClasspath - Compile classpath for source set 'test'.
+--- org.apache.activemq:activemq-all:5.11.+ -> 5.11.4
+--- mysql:mysql-connector-java:5.1.+ -> 5.1.40
+--- com.google.code.gson:gson:2.+ -> 2.8.0
+--- com.google.guava:guava:19.+ -> 19.0
+--- org.mongodb:mongo-java-driver:2.13.+ -> 2.13.3
+--- commons-cli:commons-cli:1.3.+ -> 1.3.1
+--- org.apache.logging.log4j:log4j-api:2.+ -> 2.7
+--- org.apache.logging.log4j:log4j-core:2.+ -> 2.7
|    \--- org.apache.logging.log4j:log4j-api:2.7
+--- org.apache.commons:commons-lang3:3.+ -> 3.5
\--- junit:junit:4.+ -> 4.12
     \--- org.hamcrest:hamcrest-core:1.3

Т.е. надо пулл коннектов использовать?
...
Рейтинг: 0 / 0
21.12.2016, 13:24
    #39371881
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
HettТ.е. надо пулл коннектов использовать?
Нужно использовать 1 JDBC объект на каждый поток и не шарить их между потоками. А пул это у вас будет или что-то ещё, это уже другой вопрос. А тут, не понятно где соединение, не понятно откуда Statement, не ясно где оно всё закрывается. Бедлам.
...
Рейтинг: 0 / 0
21.12.2016, 13:49
    #39371919
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
В PHP таких проблем не было (всегда жеж один поток), поэтому даже не подумал о работе одного соединения в многопоточной среде. Сессии тысячи и на каждую держать коннект не получится. Открывать на каждую запись тоже подумалось не лучшим вариантом.

Поизучал вопрос, сделал так:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    private static final BasicDataSource dataSource = new BasicDataSource();

    static {
        Properties properties = Properties.getInstance();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl(properties.getProperty("db_uri"));
        dataSource.setUsername(properties.getProperty("db_user"));
        dataSource.setPassword(properties.getProperty("db_password"));
    }

    public void touchDownload(String id) {
        try (
                PreparedStatement updateDownloadStmt = dataSource.getConnection().prepareStatement(
                        "UPDATE fh_download SET date_end = CURRENT_TIMESTAMP WHERE unique_key = ?"
                );
        ) {
            updateDownloadStmt.setString(1, id);
            updateDownloadStmt.executeUpdate();
        } catch (SQLException e) {
            DownloadMeter.logger.error("SQL error", e);
        }
    }



Единственное, что смущает, что Statement создается каждый раз, но если я правильно понял из первого беглого прочтения доки, то он все таки кэшируется?
...
Рейтинг: 0 / 0
21.12.2016, 13:51
    #39371922
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Тем не менее с драйвером MongoDB таких проблем вроде не замечено, один коннект на все потоки работает без нареканий.
...
Рейтинг: 0 / 0
21.12.2016, 14:04
    #39371936
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
HettТем не менее с драйвером MongoDB таких проблем вроде не замечено, один коннект на все потоки работает без нареканий.
Весь софт работает одинаково. Это отличное предположение, на которое стоит опираться при кодировании. Плевать на JDBC спеку.
...
Рейтинг: 0 / 0
21.12.2016, 14:16
    #39371953
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
В доке говорят, что можно шарить между потоками:

авторThe MongoClient class is designed to be thread safe and shared among threads. Typically you create only 1 instance for a given database cluster and use it across your application.
http://mongodb.github.io/mongo-java-driver/2.13/getting-started/quick-tour/
...
Рейтинг: 0 / 0
21.12.2016, 14:29
    #39371966
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Hett,

Работать с MySQL через JDBC и руководствоваться при этом докой по MongoDB это пять.
...
Рейтинг: 0 / 0
21.12.2016, 15:09
    #39372025
Hett
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
guava UncheckedExecutionException
Я не изучал доки досконально. Конкретно по работе с потоками стал разбирать только когда с проблемой столкнулся. Про монгу отписался по мере прочтения доки, так как заподозрил что и там подобная проблема есть.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / guava UncheckedExecutionException / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]