Observed this issue when trying load class by URLClassLoader by http://server:port/filename, where the server is a simple HttpServer.
To demonstrate the issue, please see below test. The simple HttpServer just sendResponseHeaders(404, -1) when getting the request. But this simple server sometime hangs. In case of hang, no log, no output.
import com.sun.net.httpserver.*;
import java.io.IOException;
import java.net.*;
import java.util.logging.*;
public class URLClassLoaderTest {
public static void main(String[] args) throws IOException {
enableLogging();
HttpServer server = null;
try {
server = HttpServer.create(new InetSocketAddress(0), 0);
server.createContext("/test.jar", new MyHttpHandler());
server.setExecutor(null); // creates a default executor
server.start();
URL[] urls = new URL[]{
new URL("http://localhost:" + server.getAddress().getPort() + "/test.jar")
};
ClassLoader cldr = new URLClassLoader(urls);
try {
cldr.loadClass("test.Main");
} catch (ClassNotFoundException cnfe) {
//ignore
}
System.out.println("Test PASS");
} finally {
if (server != null) {
server.stop(0);
}
}
}
private static void enableLogging() {
Logger logger = Logger.getLogger("");
Handler h = (new StreamHandler(System.out, new SimpleFormatter()));
h.setLevel(Level.ALL);
logger.setLevel(Level.ALL);
logger.addHandler(h);
}
private static class MyHttpHandler implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
try {
byte[] requestBytes = t.getRequestBody().readAllBytes(); // consume request
System.out.println("DEBUG:: SimpleHttpServer got requestbody length = " + requestBytes.length);
t.sendResponseHeaders(404, -1);
} catch (Exception e) {
System.out.println("DEBUG:: SimpleHttpServer got exception: " + e.getMessage());
e.printStackTrace();
throw e;
}
}
}
}
In case of hang, no log, no output at all.
Thread dump looks like (full dump attached):
==================================
Full thread dump Java HotSpot(TM) 64-Bit Server VM (9-ea+170 mixed mode):
"Attach Listener" #15 daemon prio=9 os_prio=64 tid=0x00000001007bc800 nid=0x25 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00000001007bc800 [0x25] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
"HTTP-Dispatcher" #14 prio=5 os_prio=64 tid=0x0000000101102800 nid=0x24 runnable [0xffffffff49bfe000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_in_native
Thread: 0x0000000101102800 [0x24] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_in_native
at sun.nio.ch.DevPollArrayWrapper.poll0(java.base@9-ea/Native Method)
at sun.nio.ch.DevPollArrayWrapper.poll(java.base@9-ea/DevPollArrayWrapper.java:223)
at sun.nio.ch.DevPollSelectorImpl.doSelect(java.base@9-ea/DevPollSelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@9-ea/SelectorImpl.java:86)
- locked <0x00000006d2d65668> (a sun.nio.ch.Util$2)
- locked <0x00000006d2d655d8> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000006d2d64fe8> (a sun.nio.ch.DevPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(java.base@9-ea/SelectorImpl.java:97)
at sun.net.httpserver.ServerImpl$Dispatcher.run(jdk.httpserver@9-ea/ServerImpl.java:361)
at java.lang.Thread.run(java.base@9-ea/Thread.java:844)
...
"main" #1 prio=5 os_prio=64 tid=0x00000001001bd000 nid=0x2 runnable [0xffffffff7cffa000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_in_native
Thread: 0x00000001001bd000 [0x 2] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_in_native
at java.net.SocketInputStream.socketRead0(java.base@9-ea/Native Method)
at java.net.SocketInputStream.socketRead(java.base@9-ea/SocketInputStream.java:116)
at java.net.SocketInputStream.read(java.base@9-ea/SocketInputStream.java:171)
at java.net.SocketInputStream.read(java.base@9-ea/SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(java.base@9-ea/BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(java.base@9-ea/BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(java.base@9-ea/BufferedInputStream.java:345)
- locked <0x00000006d2921b70> (a java.io.BufferedInputStream)
at sun.net.www.http.HttpClient.parseHTTPHeader(java.base@9-ea/HttpClient.java:746)
at sun.net.www.http.HttpClient.parseHTTP(java.base@9-ea/HttpClient.java:689)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(java.base@9-ea/HttpURLConnection.java:1586)
- locked <0x00000006d2905f10> (a sun.net.www.protocol.http.HttpURLConnection)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(java.base@9-ea/HttpURLConnection.java:1491)
- locked <0x00000006d2905f10> (a sun.net.www.protocol.http.HttpURLConnection)
at sun.net.www.protocol.jar.URLJarFile.retrieve(java.base@9-ea/URLJarFile.java:212)
...
To demonstrate the issue, please see below test. The simple HttpServer just sendResponseHeaders(404, -1) when getting the request. But this simple server sometime hangs. In case of hang, no log, no output.
import com.sun.net.httpserver.*;
import java.io.IOException;
import java.net.*;
import java.util.logging.*;
public class URLClassLoaderTest {
public static void main(String[] args) throws IOException {
enableLogging();
HttpServer server = null;
try {
server = HttpServer.create(new InetSocketAddress(0), 0);
server.createContext("/test.jar", new MyHttpHandler());
server.setExecutor(null); // creates a default executor
server.start();
URL[] urls = new URL[]{
new URL("http://localhost:" + server.getAddress().getPort() + "/test.jar")
};
ClassLoader cldr = new URLClassLoader(urls);
try {
cldr.loadClass("test.Main");
} catch (ClassNotFoundException cnfe) {
//ignore
}
System.out.println("Test PASS");
} finally {
if (server != null) {
server.stop(0);
}
}
}
private static void enableLogging() {
Logger logger = Logger.getLogger("");
Handler h = (new StreamHandler(System.out, new SimpleFormatter()));
h.setLevel(Level.ALL);
logger.setLevel(Level.ALL);
logger.addHandler(h);
}
private static class MyHttpHandler implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
try {
byte[] requestBytes = t.getRequestBody().readAllBytes(); // consume request
System.out.println("DEBUG:: SimpleHttpServer got requestbody length = " + requestBytes.length);
t.sendResponseHeaders(404, -1);
} catch (Exception e) {
System.out.println("DEBUG:: SimpleHttpServer got exception: " + e.getMessage());
e.printStackTrace();
throw e;
}
}
}
}
In case of hang, no log, no output at all.
Thread dump looks like (full dump attached):
==================================
Full thread dump Java HotSpot(TM) 64-Bit Server VM (9-ea+170 mixed mode):
"Attach Listener" #15 daemon prio=9 os_prio=64 tid=0x00000001007bc800 nid=0x25 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_blocked
Thread: 0x00000001007bc800 [0x25] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_blocked
"HTTP-Dispatcher" #14 prio=5 os_prio=64 tid=0x0000000101102800 nid=0x24 runnable [0xffffffff49bfe000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_in_native
Thread: 0x0000000101102800 [0x24] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_in_native
at sun.nio.ch.DevPollArrayWrapper.poll0(java.base@9-ea/Native Method)
at sun.nio.ch.DevPollArrayWrapper.poll(java.base@9-ea/DevPollArrayWrapper.java:223)
at sun.nio.ch.DevPollSelectorImpl.doSelect(java.base@9-ea/DevPollSelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@9-ea/SelectorImpl.java:86)
- locked <0x00000006d2d65668> (a sun.nio.ch.Util$2)
- locked <0x00000006d2d655d8> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000006d2d64fe8> (a sun.nio.ch.DevPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(java.base@9-ea/SelectorImpl.java:97)
at sun.net.httpserver.ServerImpl$Dispatcher.run(jdk.httpserver@9-ea/ServerImpl.java:361)
at java.lang.Thread.run(java.base@9-ea/Thread.java:844)
...
"main" #1 prio=5 os_prio=64 tid=0x00000001001bd000 nid=0x2 runnable [0xffffffff7cffa000]
java.lang.Thread.State: RUNNABLE
JavaThread state: _thread_in_native
Thread: 0x00000001001bd000 [0x 2] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0
JavaThread state: _thread_in_native
at java.net.SocketInputStream.socketRead0(java.base@9-ea/Native Method)
at java.net.SocketInputStream.socketRead(java.base@9-ea/SocketInputStream.java:116)
at java.net.SocketInputStream.read(java.base@9-ea/SocketInputStream.java:171)
at java.net.SocketInputStream.read(java.base@9-ea/SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(java.base@9-ea/BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(java.base@9-ea/BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(java.base@9-ea/BufferedInputStream.java:345)
- locked <0x00000006d2921b70> (a java.io.BufferedInputStream)
at sun.net.www.http.HttpClient.parseHTTPHeader(java.base@9-ea/HttpClient.java:746)
at sun.net.www.http.HttpClient.parseHTTP(java.base@9-ea/HttpClient.java:689)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(java.base@9-ea/HttpURLConnection.java:1586)
- locked <0x00000006d2905f10> (a sun.net.www.protocol.http.HttpURLConnection)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(java.base@9-ea/HttpURLConnection.java:1491)
- locked <0x00000006d2905f10> (a sun.net.www.protocol.http.HttpURLConnection)
at sun.net.www.protocol.jar.URLJarFile.retrieve(java.base@9-ea/URLJarFile.java:212)
...
- relates to
-
JDK-8158899 java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java fails with CNFE
-
- Open
-