1 /* 2 * Copyright (c) 2008, 2013, 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 }