001: /*
002: Copyright (c) 2005, MentorGen, LLC
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions are met:
007:
008: + Redistributions of source code must retain the above copyright notice,
009: this list of conditions and the following disclaimer.
010: + Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: + Neither the name of MentorGen LLC nor the names of its contributors may be
014: used to endorse or promote products derived from this software without
015: specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
021: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
022: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
023: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
024: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
025: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
026: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
027: POSSIBILITY OF SUCH DAMAGE.
028: */
029: package com.mentorgen.tools.profile.instrument;
030:
031: import java.lang.instrument.ClassFileTransformer;
032: import java.lang.instrument.IllegalClassFormatException;
033: import java.security.ProtectionDomain;
034:
035: import org.objectweb.asm.jip.ClassAdapter;
036: import org.objectweb.asm.jip.ClassReader;
037: import org.objectweb.asm.jip.ClassWriter;
038:
039: import com.mentorgen.tools.profile.Controller;
040:
041: /**
042: * This class determines if a given class should be instrumented
043: * with profiling code or not. The property <code>debug</code>, when
044: * set to <code>on</code>, will show you which classes are being instrumented
045: * and what ones are not.
046: *
047: * @author Andrew Wilcox
048: * @see java.lang.instrument.ClassFileTransformer
049: */
050: public class Transformer implements ClassFileTransformer {
051:
052: public byte[] transform(ClassLoader loader, String className,
053: Class<?> classBeingRedefined,
054: ProtectionDomain protectionDomain, byte[] classfileBuffer)
055: throws IllegalClassFormatException {
056:
057: // can't profile yourself
058: //
059: if (className.startsWith("com/mentorgen/tools/profile")
060: || className.startsWith("net/sourceforge/jiprof")) {
061: return classfileBuffer;
062: }
063:
064: // include
065: //
066: if (Controller._includeList.length > 0) {
067: boolean toInclude = false;
068:
069: for (String include : Controller._includeList) {
070: if (className.startsWith(include)) {
071: toInclude = true;
072: break;
073: }
074: }
075:
076: if (!toInclude) {
077: if (Controller._debug) {
078: debug(loader, className, false);
079: }
080:
081: return classfileBuffer;
082: }
083: }
084:
085: if (!Controller._filter.accept(loader)) {
086:
087: if (Controller._debug) {
088: debug(loader, className, false);
089: }
090:
091: return classfileBuffer;
092: }
093:
094: // exclude
095: //
096: for (String exclude : Controller._excludeList) {
097: if (className.startsWith(exclude)) {
098: if (Controller._debug) {
099: debug(loader, className, false);
100: }
101: return classfileBuffer;
102: }
103: }
104:
105: byte[] result = classfileBuffer;
106: try {
107: if (Controller._debug) {
108: debug(loader, className, true);
109: }
110:
111: Controller._instrumentCount++;
112:
113: ClassReader reader = new ClassReader(classfileBuffer);
114: ClassWriter writer = new ClassWriter(true);
115: ClassAdapter adapter = new PerfClassAdapter(writer,
116: className);
117: reader.accept(adapter, true);
118: result = writer.toByteArray();
119: } catch (Throwable t) {
120: t.printStackTrace();
121: throw new RuntimeException(t);
122: }
123:
124: return result;
125: }
126:
127: private void debug(ClassLoader loader, String className,
128: boolean transformed) {
129: StringBuffer b = new StringBuffer();
130:
131: if (transformed) {
132: b.append("INST");
133: } else {
134: b.append("skip");
135: }
136:
137: b.append("\t");
138: b.append(className);
139: b.append("\t");
140: b.append("[");
141: b.append(loader.getClass().getName());
142: b.append("]");
143: System.out.println(b.toString());
144: }
145: }
|