jdk/src/jdk.runtime/share/classes/sun/tracing/dtrace/DTraceProvider.java
changeset 29262 1698800c8606
parent 29261 ea6e20f98dfa
parent 29099 766801b4d95d
child 29263 66e30e926405
child 29505 682be03b8f41
equal deleted inserted replaced
29261:ea6e20f98dfa 29262:1698800c8606
     1 /*
       
     2  * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.tracing.dtrace;
       
    27 
       
    28 import java.lang.reflect.Method;
       
    29 import java.lang.reflect.Modifier;
       
    30 import java.lang.reflect.Constructor;
       
    31 import java.lang.reflect.InvocationHandler;
       
    32 import java.lang.reflect.InvocationTargetException;
       
    33 import java.lang.annotation.Annotation;
       
    34 
       
    35 import sun.tracing.ProviderSkeleton;
       
    36 import sun.tracing.ProbeSkeleton;
       
    37 import com.sun.tracing.Provider;
       
    38 import com.sun.tracing.ProbeName;
       
    39 import com.sun.tracing.dtrace.Attributes;
       
    40 import com.sun.tracing.dtrace.ModuleName;
       
    41 import com.sun.tracing.dtrace.FunctionName;
       
    42 import com.sun.tracing.dtrace.StabilityLevel;
       
    43 import com.sun.tracing.dtrace.DependencyClass;
       
    44 
       
    45 import sun.misc.ProxyGenerator;
       
    46 
       
    47 class DTraceProvider extends ProviderSkeleton {
       
    48 
       
    49     private Activation activation;
       
    50     private Object proxy;
       
    51 
       
    52     // For proxy generation
       
    53     private final static Class<?>[] constructorParams = { InvocationHandler.class };
       
    54     private final String proxyClassNamePrefix = "$DTraceTracingProxy";
       
    55 
       
    56     static final String DEFAULT_MODULE = "java_tracing";
       
    57     static final String DEFAULT_FUNCTION = "unspecified";
       
    58 
       
    59     private static long nextUniqueNumber = 0;
       
    60     private static synchronized long getUniqueNumber() {
       
    61         return nextUniqueNumber++;
       
    62     }
       
    63 
       
    64     protected ProbeSkeleton createProbe(Method m) {
       
    65         return new DTraceProbe(proxy, m);
       
    66     }
       
    67 
       
    68     DTraceProvider(Class<? extends Provider> type) {
       
    69         super(type);
       
    70     }
       
    71 
       
    72     void setProxy(Object p) {
       
    73         proxy = p;
       
    74     }
       
    75 
       
    76     void setActivation(Activation a) {
       
    77         this.activation = a;
       
    78     }
       
    79 
       
    80     public void dispose() {
       
    81         if (activation != null) {
       
    82             activation.disposeProvider(this);
       
    83             activation = null;
       
    84         }
       
    85         super.dispose();
       
    86     }
       
    87 
       
    88     /**
       
    89      * Magic routine which creates an implementation of the user's interface.
       
    90      *
       
    91      * This method uses the ProxyGenerator directly to bypass the
       
    92      * java.lang.reflect.proxy cache so that we get a unique class each
       
    93      * time it's called and can't accidently reuse a $Proxy class.
       
    94      *
       
    95      * @return an implementation of the user's interface
       
    96      */
       
    97     @SuppressWarnings("unchecked")
       
    98     public <T extends Provider> T newProxyInstance() {
       
    99         /*
       
   100          * Choose a name for the proxy class to generate.
       
   101          */
       
   102         long num = getUniqueNumber();
       
   103 
       
   104         String proxyPkg = "";
       
   105         if (!Modifier.isPublic(providerType.getModifiers())) {
       
   106             String name = providerType.getName();
       
   107             int n = name.lastIndexOf('.');
       
   108             proxyPkg = ((n == -1) ? "" : name.substring(0, n + 1));
       
   109         }
       
   110 
       
   111         String proxyName = proxyPkg + proxyClassNamePrefix + num;
       
   112 
       
   113         /*
       
   114          * Generate the specified proxy class.
       
   115          */
       
   116         Class<?> proxyClass = null;
       
   117         byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
       
   118                 proxyName, new Class<?>[] { providerType });
       
   119         try {
       
   120             proxyClass = JVM.defineClass(
       
   121                 providerType.getClassLoader(), proxyName,
       
   122                 proxyClassFile, 0, proxyClassFile.length);
       
   123         } catch (ClassFormatError e) {
       
   124             /*
       
   125              * A ClassFormatError here means that (barring bugs in the
       
   126              * proxy class generation code) there was some other
       
   127              * invalid aspect of the arguments supplied to the proxy
       
   128              * class creation (such as virtual machine limitations
       
   129              * exceeded).
       
   130              */
       
   131             throw new IllegalArgumentException(e.toString());
       
   132         }
       
   133 
       
   134         /*
       
   135          * Invoke its constructor with the designated invocation handler.
       
   136          */
       
   137         try {
       
   138             Constructor<?> cons = proxyClass.getConstructor(constructorParams);
       
   139             return (T)cons.newInstance(new Object[] { this });
       
   140         } catch (ReflectiveOperationException e) {
       
   141             throw new InternalError(e.toString(), e);
       
   142         }
       
   143     }
       
   144 
       
   145     // In the normal case, the proxy object's method implementations will call
       
   146     // this method (it usually calls the ProviderSkeleton's version).  That
       
   147     // method uses the passed 'method' object to lookup the associated
       
   148     // 'ProbeSkeleton' and calls uncheckedTrigger() on that probe to cause the
       
   149     // probe to fire.  DTrace probes are different in that the proxy class's
       
   150     // methods are immediately overridden with native code to fire the probe
       
   151     // directly.  So this method should never get invoked.  We also wire up the
       
   152     // DTraceProbe.uncheckedTrigger() method to call the proxy method instead
       
   153     // of doing the work itself.
       
   154     protected void triggerProbe(Method method, Object[] args) {
       
   155         assert false : "This method should have been overridden by the JVM";
       
   156     }
       
   157 
       
   158     public String getProviderName() {
       
   159         return super.getProviderName();
       
   160     }
       
   161 
       
   162     String getModuleName() {
       
   163         return getAnnotationString(
       
   164             providerType, ModuleName.class, DEFAULT_MODULE);
       
   165     }
       
   166 
       
   167     static String getProbeName(Method method) {
       
   168         return getAnnotationString(
       
   169             method, ProbeName.class, method.getName());
       
   170     }
       
   171 
       
   172     static String getFunctionName(Method method) {
       
   173         return getAnnotationString(
       
   174             method, FunctionName.class, DEFAULT_FUNCTION);
       
   175     }
       
   176 
       
   177     DTraceProbe[] getProbes() {
       
   178         return probes.values().toArray(new DTraceProbe[0]);
       
   179     }
       
   180 
       
   181     StabilityLevel getNameStabilityFor(Class<? extends Annotation> type) {
       
   182         Attributes attrs = (Attributes)getAnnotationValue(
       
   183             providerType, type, "value", null);
       
   184         if (attrs == null) {
       
   185             return StabilityLevel.PRIVATE;
       
   186         } else {
       
   187             return attrs.name();
       
   188         }
       
   189     }
       
   190 
       
   191     StabilityLevel getDataStabilityFor(Class<? extends Annotation> type) {
       
   192         Attributes attrs = (Attributes)getAnnotationValue(
       
   193             providerType, type, "value", null);
       
   194         if (attrs == null) {
       
   195             return StabilityLevel.PRIVATE;
       
   196         } else {
       
   197             return attrs.data();
       
   198         }
       
   199     }
       
   200 
       
   201     DependencyClass getDependencyClassFor(Class<? extends Annotation> type) {
       
   202         Attributes attrs = (Attributes)getAnnotationValue(
       
   203             providerType, type, "value", null);
       
   204         if (attrs == null) {
       
   205             return DependencyClass.UNKNOWN;
       
   206         } else {
       
   207             return attrs.dependency();
       
   208         }
       
   209     }
       
   210 }