getOption() and setOption() methods of jdk.net.Sockets class throw InvocationTargetException instead of actual runtime exceptions like NullPointerException and AccessControlException:
Exception in thread "main" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at jdk.net.Sockets.invokeGet(Sockets.java:140)
at jdk.net.Sockets.getOption(Sockets.java:202)
at Utils.getOption(Utils.java:41)
at NetworkPermissionTest.checkNetworkPermission(NetworkPermissionTest.java:49)
at Test.doTest(Test.java:24)
at NetworkPermissionTest.run(NetworkPermissionTest.java:36)
at Test.main(Test.java:20)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at jdk.net.Sockets.invokeGet(Sockets.java:132)
... 6 more
Caused by: java.security.AccessControlException: access denied ("jdk.net.NetworkPermission" "getOption.SO_FLOW_SLA")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:457)
at java.security.AccessController.checkPermission(AccessController.java:884)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at sun.net.ExtendedOptionsImpl.checkGetOptionPermission(ExtendedOptionsImpl.java:71)
at java.net.PlainSocketImpl.getOption(PlainSocketImpl.java:80)
at java.net.SocketSecrets.getOption(SocketSecrets.java:59)
... 11 more
Please see attached test to reproduce the issue (test.tar.gz). The test expects AccessControlException. The issue is reproducible only on Solaris 11.2 that supports SO_FLOW_SLA socket option.
invokeGet() and invokeSet() methods handle only IOException, see http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/7f04532ee859/src/share/classes/jdk/net/Sockets.java
...
private static <T> void invokeSet(
Method method, Object socket,
SocketOption<T> option, T value) throws IOException
{
try {
method.invoke(null, socket, option, value);
} catch (Exception e) {
if (e instanceof InvocationTargetException) {
Throwable t = ((InvocationTargetException)e).getTargetException();
if (t instanceof IOException) {
throw (IOException)t;
}
}
throw new RuntimeException(e);
}
}
...
It is not a regression because this API was introduced in 8u20, see JDK-8032808.
I think it is better to throw an original runtime exception to reduce and simplify stack traces. For example, it can be fixed like the following:
...
} catch (Exception e) {
if (e instanceof InvocationTargetException) {
Throwable t = ((InvocationTargetException)e).getTargetException();
if (t instanceof IOException) {
throw (IOException)t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException)t;
}
}
throw new RuntimeException(e);
}
...
Please see http://cr.openjdk.java.net/~asmotrak/so_flow_sla/sockets_exceptions/webrev.00