Istnieje rozwiązanie tego problemu na niektórych forach OTN (https://kr.forums.oracle.com/forums/thread.jspa?messageID=3699989). Ale główna przyczyna problemu nie została wyjaśniona. Poniżej znajduje się moja próba wyjaśnienia głównej przyczyny problemu.
Sterowniki Oracle JDBC komunikują się z serwerem Oracle w bezpieczny sposób. Sterowniki używają java.security.SecureRandom klasa do gromadzenia entropii w celu zabezpieczenia komunikacji. Ta klasa opiera się na natywnej obsłudze platformy do gromadzenia entropii.
Entropia to losowość zbierana/generowana przez system operacyjny lub aplikację do użytku w kryptografii lub innych zastosowaniach wymagających losowych danych. Ta losowość jest często zbierana ze źródeł sprzętowych, z szumów sprzętowych, danych audio, ruchów myszy lub specjalnie dostarczonych generatorów losowości. Jądro gromadzi entropię i przechowuje ją jako pulę entropii i udostępnia losowe dane znakowe procesom lub aplikacjom systemu operacyjnego za pośrednictwem specjalnych plików /dev/random i /dev/urandom .
Czytanie z /dev/random drenuje pulę entropii żądaną ilością bitów/bajtów, zapewniając wysoki stopień losowości, często pożądanej w operacjach kryptograficznych. W przypadku, gdy pula entropii jest całkowicie wyczerpana, a wystarczająca entropia nie jest dostępna, operacja odczytu na /dev/random bloki do momentu zgromadzenia dodatkowej entropii. Z tego powodu aplikacje czytające z /dev/random może blokować się na pewien losowy okres czasu.
W przeciwieństwie do powyższego, czytanie z /dev/urandom nie blokuje. Czytanie z /dev/urandom , również drenuje pulę entropii, ale gdy brakuje wystarczającej entropii, nie blokuje, ale ponownie wykorzystuje bity z częściowo odczytanych losowych danych. Mówi się, że jest to podatne na ataki kryptoanalityczne. Jest to teoretyczna możliwość i dlatego odradza się czytanie z /dev/urandom do zbierania losowości w operacjach kryptograficznych.
java.security.SecureRandom domyślnie czyta z /dev/random plik, a zatem czasami blokuje się na losowy okres czasu. Teraz, jeśli operacja odczytu nie powraca przez wymagany czas, serwer Oracle przekracza limit czasu klienta (w tym przypadku sterowniki jdbc) i przerywa komunikację, zamykając gniazdo od jego końca. Klient, gdy próbuje wznowić komunikację po powrocie z wywołania blokującego, napotyka wyjątek IO. Ten problem może wystąpić losowo na dowolnej platformie, zwłaszcza gdy entropia jest zbierana z szumów sprzętowych.
Jak zasugerowano na forum OTN, rozwiązaniem tego problemu jest zastąpienie domyślnego zachowania java.security.SecureRandom klasa do użycia nieblokującego odczytu z /dev/urandom zamiast blokowania odczytanego z /dev/random . Można to zrobić, dodając następującą właściwość systemową -Djava.security.egd=file:///dev/urandom do JVM. Chociaż jest to dobre rozwiązanie dla aplikacji takich jak sterowniki JDBC, odradza się to w przypadku aplikacji, które wykonują podstawowe operacje kryptograficzne, takie jak generowanie kluczy kryptograficznych.
Inne rozwiązania mogą polegać na użyciu różnych implementacji siewnika losowego dostępnych dla platformy, które nie opierają się na szumach sprzętowych do gromadzenia entropii. Dzięki temu możesz nadal wymagać zastąpienia domyślnego zachowania java.security.SecureRandom .
Rozwiązaniem może być również zwiększenie limitu czasu gniazda po stronie serwera Oracle, ale skutki uboczne należy ocenić z punktu widzenia serwera przed podjęciem takiej próby.