# HG changeset patch
# User mkos
# Date 1383022122 0
#      Tue Oct 29 04:48:42 2013 +0000
# Node ID 4ea4a060f3748510aedf4355ae2dbf2921f15494
# Parent  60ca74797572c7fb8682802738dda073e44aeea0
8017505: Better Client Service
Reviewed-by: mullan, ahgross, mgrebac

diff -r 60ca74797572 -r 4ea4a060f374 drop_included/jaxws_src/src/com/sun/xml/internal/ws/api/server/InstanceResolver.java
--- openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/api/server/InstanceResolver.java	Fri Oct 04 12:22:34 2013 -0400
+++ openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/api/server/InstanceResolver.java	Tue Oct 29 04:48:42 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -232,7 +232,7 @@
             public Object invoke(Packet p, Method m, Object... args) throws InvocationTargetException, IllegalAccessException {
                 T t = resolve(p);
                 try {
-                    return m.invoke(t, args );
+                    return MethodUtil.invoke(t, m, args );
                 } finally {
                     postInvoke(p,t);
                 }
diff -r 60ca74797572 -r 4ea4a060f374 drop_included/jaxws_src/src/com/sun/xml/internal/ws/api/server/MethodUtil.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/api/server/MethodUtil.java	Tue Oct 29 04:48:42 2013 +0000
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * http://glassfish.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.xml.internal.ws.api.server;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Utility class to invoke sun.reflect.misc.MethodUtil.invoke() if available. If not (other then Oracle JDK) fallbacks
+ * to java.lang,reflect.Method.invoke()
+ *
+ * Be careful, copy of this class exists in several packages, iny modification must be done to other copies too!
+ */
+class MethodUtil {
+
+    private static final Logger LOGGER = Logger.getLogger(MethodUtil.class.getName());
+    private static final Method INVOKE_METHOD;
+
+    static {
+        Method method;
+        try {
+            Class<?> clazz = Class.forName("sun.reflect.misc.MethodUtil");
+            method = clazz.getMethod("invoke", Method.class, Object.class, Object[].class);
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil found; it will be used to invoke methods.");
+            }
+        } catch (Throwable t) {
+            method = null;
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil not found, probably non-Oracle JVM");
+            }
+        }
+        INVOKE_METHOD = method;
+    }
+
+    static Object invoke(Object target, Method method, Object[] args) throws IllegalAccessException, InvocationTargetException {
+        if (INVOKE_METHOD != null) {
+            // sun.reflect.misc.MethodUtil.invoke(method, owner, args)
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method using sun.reflect.misc.MethodUtil");
+            }
+            try {
+                return INVOKE_METHOD.invoke(null, method, target, args);
+            } catch (InvocationTargetException ite) {
+                // unwrap invocation exception added by reflection code ...
+                throw unwrapException(ite);
+            }
+        } else {
+            // other then Oracle JDK ...
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method directly, probably non-Oracle JVM");
+            }
+            return method.invoke(target, args);
+        }
+    }
+
+    private static InvocationTargetException unwrapException(InvocationTargetException ite) {
+        Throwable targetException = ite.getTargetException();
+        if (targetException != null && targetException instanceof InvocationTargetException) {
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Unwrapping invocation target exception");
+            }
+            return (InvocationTargetException) targetException;
+        } else {
+            return ite;
+        }
+    }
+
+}
diff -r 60ca74797572 -r 4ea4a060f374 drop_included/jaxws_src/src/com/sun/xml/internal/ws/client/sei/MethodUtil.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/client/sei/MethodUtil.java	Tue Oct 29 04:48:42 2013 +0000
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * http://glassfish.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.xml.internal.ws.client.sei;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Utility class to invoke sun.reflect.misc.MethodUtil.invoke() if available. If not (other then Oracle JDK) fallbacks
+ * to java.lang,reflect.Method.invoke()
+ * <p/>
+ * Be careful, copy of this class exists in several packages, iny modification must be done to other copies too!
+ */
+class MethodUtil {
+
+    private static final Logger LOGGER = Logger.getLogger(MethodUtil.class.getName());
+    private static final Method INVOKE_METHOD;
+
+    static {
+        Method method;
+        try {
+            Class<?> clazz = Class.forName("sun.reflect.misc.MethodUtil");
+            method = clazz.getMethod("invoke", Method.class, Object.class, Object[].class);
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil found; it will be used to invoke methods.");
+            }
+        } catch (Throwable t) {
+            method = null;
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil not found, probably non-Oracle JVM");
+            }
+        }
+        INVOKE_METHOD = method;
+    }
+
+    static Object invoke(Object target, Method method, Object[] args) throws IllegalAccessException, InvocationTargetException {
+        if (INVOKE_METHOD != null) {
+            // sun.reflect.misc.MethodUtil.invoke(method, owner, args)
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method using sun.reflect.misc.MethodUtil");
+            }
+            try {
+                return INVOKE_METHOD.invoke(null, method, target, args);
+            } catch (InvocationTargetException ite) {
+                // unwrap invocation exception added by reflection code ...
+                throw unwrapException(ite);
+            }
+        } else {
+            // other then Oracle JDK ...
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method directly, probably non-Oracle JVM");
+            }
+            return method.invoke(target, args);
+        }
+    }
+
+    private static InvocationTargetException unwrapException(InvocationTargetException ite) {
+        Throwable targetException = ite.getTargetException();
+        if (targetException != null && targetException instanceof InvocationTargetException) {
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Unwrapping invocation target exception");
+            }
+            return (InvocationTargetException) targetException;
+        } else {
+            return ite;
+        }
+    }
+
+}
diff -r 60ca74797572 -r 4ea4a060f374 drop_included/jaxws_src/src/com/sun/xml/internal/ws/client/sei/SEIStub.java
--- openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/client/sei/SEIStub.java	Fri Oct 04 12:22:34 2013 -0400
+++ openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/client/sei/SEIStub.java	Tue Oct 29 04:48:42 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,8 +33,8 @@
 import com.sun.xml.internal.ws.api.message.Packet;
 import com.sun.xml.internal.ws.api.model.MEP;
 import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
+import com.sun.xml.internal.ws.api.pipe.Fiber;
 import com.sun.xml.internal.ws.api.pipe.Tube;
-import com.sun.xml.internal.ws.api.pipe.Fiber;
 import com.sun.xml.internal.ws.binding.BindingImpl;
 import com.sun.xml.internal.ws.client.RequestContext;
 import com.sun.xml.internal.ws.client.ResponseContextReceiver;
@@ -47,6 +47,8 @@
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -102,13 +104,14 @@
     private final Map<Method, MethodHandler> methodHandlers = new HashMap<Method, MethodHandler>();
 
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        validateInputs(proxy, method);
         MethodHandler handler = methodHandlers.get(method);
         if (handler != null) {
             return handler.invoke(proxy, args);
         } else {
             // we handle the other method invocations by ourselves
             try {
-                return method.invoke(this, args);
+                return MethodUtil.invoke(this, method, args);
             } catch (IllegalAccessException e) {
                 // impossible
                 throw new AssertionError(e);
@@ -120,6 +123,17 @@
         }
     }
 
+    private void validateInputs(Object proxy, Method method) {
+        if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) {
+            throw new IllegalStateException("Passed object is not proxy!");
+        }
+        Class<?> declaringClass = method.getDeclaringClass();
+        if (method == null || declaringClass == null
+                || Modifier.isStatic(method.getModifiers())) {
+            throw new IllegalStateException("Invoking static method is not allowed!");
+        }
+    }
+
     public final Packet doProcess(Packet request, RequestContext rc, ResponseContextReceiver receiver) {
         return super.process(request, rc, receiver);
     }
diff -r 60ca74797572 -r 4ea4a060f374 drop_included/jaxws_src/src/com/sun/xml/internal/ws/policy/privateutil/MethodUtil.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/policy/privateutil/MethodUtil.java	Tue Oct 29 04:48:42 2013 +0000
@@ -0,0 +1,107 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * http://glassfish.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.xml.internal.ws.policy.privateutil;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Utility class to invoke sun.reflect.misc.MethodUtil.invoke() if available. If not (other then Oracle JDK) fallbacks
+ * to java.lang,reflect.Method.invoke()
+ */
+class MethodUtil {
+
+    private static final Logger LOGGER = Logger.getLogger(MethodUtil.class.getName());
+    private static final Method INVOKE_METHOD;
+
+    static {
+        Method method;
+        try {
+            Class<?> clazz = Class.forName("sun.reflect.misc.MethodUtil");
+            method = clazz.getMethod("invoke", Method.class, Object.class, Object[].class);
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil found; it will be used to invoke methods.");
+            }
+        } catch (Throwable t) {
+            method = null;
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil not found, probably non-Oracle JVM");
+            }
+        }
+        INVOKE_METHOD = method;
+    }
+
+    static Object invoke(Object target, Method method, Object[] args) throws IllegalAccessException, InvocationTargetException {
+        if (INVOKE_METHOD != null) {
+            // sun.reflect.misc.MethodUtil.invoke(method, owner, args)
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method using sun.reflect.misc.MethodUtil");
+            }
+            try {
+                return INVOKE_METHOD.invoke(null, method, target, args);
+            } catch (InvocationTargetException ite) {
+                // unwrap invocation exception added by reflection code ...
+                throw unwrapException(ite);
+            }
+        } else {
+            // other then Oracle JDK ...
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method directly, probably non-Oracle JVM");
+            }
+            return method.invoke(target, args);
+        }
+    }
+
+    private static InvocationTargetException unwrapException(InvocationTargetException ite) {
+        Throwable targetException = ite.getTargetException();
+        if (targetException != null && targetException instanceof InvocationTargetException) {
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Unwrapping invocation target exception");
+            }
+            return (InvocationTargetException) targetException;
+        } else {
+            return ite;
+        }
+    }
+
+}
diff -r 60ca74797572 -r 4ea4a060f374 drop_included/jaxws_src/src/com/sun/xml/internal/ws/server/AbstractInstanceResolver.java
--- openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/server/AbstractInstanceResolver.java	Fri Oct 04 12:22:34 2013 -0400
+++ openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/server/AbstractInstanceResolver.java	Tue Oct 29 04:48:42 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -157,7 +157,7 @@
                     if (!method.isAccessible()) {
                         method.setAccessible(true);
                     }
-                    method.invoke(instance,args);
+                    MethodUtil.invoke(instance,method,args);
                 } catch (IllegalAccessException e) {
                     throw new ServerRtException("server.rt.err",e);
                 } catch (InvocationTargetException e) {
diff -r 60ca74797572 -r 4ea4a060f374 drop_included/jaxws_src/src/com/sun/xml/internal/ws/server/MethodUtil.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ openjdk/jaxws/drop_included/jaxws_src/src/com/sun/xml/internal/ws/server/MethodUtil.java	Tue Oct 29 04:48:42 2013 +0000
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * http://glassfish.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.xml.internal.ws.server;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Utility class to invoke sun.reflect.misc.MethodUtil.invoke() if available. If not (other then Oracle JDK) fallbacks
+ * to java.lang,reflect.Method.invoke()
+ *
+ * Be careful, copy of this class exists in several packages, iny modification must be done to other copies too!
+ */
+class MethodUtil {
+
+    private static final Logger LOGGER = Logger.getLogger(MethodUtil.class.getName());
+    private static final Method INVOKE_METHOD;
+
+    static {
+        Method method;
+        try {
+            Class<?> clazz = Class.forName("sun.reflect.misc.MethodUtil");
+            method = clazz.getMethod("invoke", Method.class, Object.class, Object[].class);
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil found; it will be used to invoke methods.");
+            }
+        } catch (Throwable t) {
+            method = null;
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Class sun.reflect.misc.MethodUtil not found, probably non-Oracle JVM");
+            }
+        }
+        INVOKE_METHOD = method;
+    }
+
+    static Object invoke(Object target, Method method, Object[] args) throws IllegalAccessException, InvocationTargetException {
+        if (INVOKE_METHOD != null) {
+            // sun.reflect.misc.MethodUtil.invoke(method, owner, args)
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method using sun.reflect.misc.MethodUtil");
+            }
+            try {
+                return INVOKE_METHOD.invoke(null, method, target, args);
+            } catch (InvocationTargetException ite) {
+                // unwrap invocation exception added by reflection code ...
+                throw unwrapException(ite);
+            }
+        } else {
+            // other then Oracle JDK ...
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Invoking method directly, probably non-Oracle JVM");
+            }
+            return method.invoke(target, args);
+        }
+    }
+
+    private static InvocationTargetException unwrapException(InvocationTargetException ite) {
+        Throwable targetException = ite.getTargetException();
+        if (targetException != null && targetException instanceof InvocationTargetException) {
+            if (LOGGER.isLoggable(Level.FINE)) {
+                LOGGER.log(Level.FINE, "Unwrapping invocation target exception");
+            }
+            return (InvocationTargetException) targetException;
+        } else {
+            return ite;
+        }
+    }
+
+}
