JDK-8047186 : jdk.net.Sockets throws InvocationTargetException instead of original runtime exceptions
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 8u20
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_11
  • Submitted: 2014-06-18
  • Updated: 2015-02-02
  • Resolved: 2014-06-24
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u80Fixed 8u40 b01Fixed
Related Reports
Relates :  
Relates :  
Description
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
Comments
I don't see that reflection API is used in 9: http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/d02b062bc827/src/share/classes/jdk/net/Sockets.java Seems only 8u20 is affected.
18-06-2014

jdk/net/Sockets/Test.java tests catches the issue, but it fails due to test bug JDK-8047187.
18-06-2014