Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/instrument/TransformerManager.java
38829 views
/*1* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.instrument;262728import java.lang.instrument.Instrumentation;29import java.lang.instrument.ClassFileTransformer;30import java.security.ProtectionDomain;3132/*33* Copyright 2003 Wily Technology, Inc.34*/3536/**37* Support class for the InstrumentationImpl. Manages the list of registered transformers.38* Keeps everything in the right order, deals with sync of the list,39* and actually does the calling of the transformers.40*/41public class TransformerManager42{43private class TransformerInfo {44final ClassFileTransformer mTransformer;45String mPrefix;4647TransformerInfo(ClassFileTransformer transformer) {48mTransformer = transformer;49mPrefix = null;50}5152ClassFileTransformer transformer() {53return mTransformer;54}5556String getPrefix() {57return mPrefix;58}5960void setPrefix(String prefix) {61mPrefix = prefix;62}63}6465/**66* a given instance of this list is treated as immutable to simplify sync;67* we pay copying overhead whenever the list is changed rather than every time68* the list is referenced.69* The array is kept in the order the transformers are added via addTransformer70* (first added is 0, last added is length-1)71* Use an array, not a List or other Collection. This keeps the set of classes72* used by this code to a minimum. We want as few dependencies as possible in this73* code, since it is used inside the class definition system. Any class referenced here74* cannot be transformed by Java code.75*/76private TransformerInfo[] mTransformerList;7778/***79* Is this TransformerManager for transformers capable of retransformation?80*/81private boolean mIsRetransformable;8283TransformerManager(boolean isRetransformable) {84mTransformerList = new TransformerInfo[0];85mIsRetransformable = isRetransformable;86}8788boolean isRetransformable() {89return mIsRetransformable;90}9192public synchronized void93addTransformer( ClassFileTransformer transformer) {94TransformerInfo[] oldList = mTransformerList;95TransformerInfo[] newList = new TransformerInfo[oldList.length + 1];96System.arraycopy( oldList,970,98newList,990,100oldList.length);101newList[oldList.length] = new TransformerInfo(transformer);102mTransformerList = newList;103}104105public synchronized boolean106removeTransformer(ClassFileTransformer transformer) {107boolean found = false;108TransformerInfo[] oldList = mTransformerList;109int oldLength = oldList.length;110int newLength = oldLength - 1;111112// look for it in the list, starting at the last added, and remember113// where it was if we found it114int matchingIndex = 0;115for ( int x = oldLength - 1; x >= 0; x-- ) {116if ( oldList[x].transformer() == transformer ) {117found = true;118matchingIndex = x;119break;120}121}122123// make a copy of the array without the matching element124if ( found ) {125TransformerInfo[] newList = new TransformerInfo[newLength];126127// copy up to but not including the match128if ( matchingIndex > 0 ) {129System.arraycopy( oldList,1300,131newList,1320,133matchingIndex);134}135136// if there is anything after the match, copy it as well137if ( matchingIndex < (newLength) ) {138System.arraycopy( oldList,139matchingIndex + 1,140newList,141matchingIndex,142(newLength) - matchingIndex);143}144mTransformerList = newList;145}146return found;147}148149synchronized boolean150includesTransformer(ClassFileTransformer transformer) {151for (TransformerInfo info : mTransformerList) {152if ( info.transformer() == transformer ) {153return true;154}155}156return false;157}158159// This function doesn't actually snapshot anything, but should be160// used to set a local variable, which will snapshot the transformer161// list because of the copying semantics of mTransformerList (see162// the comment for mTransformerList).163private TransformerInfo[]164getSnapshotTransformerList() {165return mTransformerList;166}167168public byte[]169transform( ClassLoader loader,170String classname,171Class<?> classBeingRedefined,172ProtectionDomain protectionDomain,173byte[] classfileBuffer) {174boolean someoneTouchedTheBytecode = false;175176TransformerInfo[] transformerList = getSnapshotTransformerList();177178byte[] bufferToUse = classfileBuffer;179180// order matters, gotta run 'em in the order they were added181for ( int x = 0; x < transformerList.length; x++ ) {182TransformerInfo transformerInfo = transformerList[x];183ClassFileTransformer transformer = transformerInfo.transformer();184byte[] transformedBytes = null;185186try {187transformedBytes = transformer.transform( loader,188classname,189classBeingRedefined,190protectionDomain,191bufferToUse);192}193catch (Throwable t) {194// don't let any one transformer mess it up for the others.195// This is where we need to put some logging. What should go here? FIXME196}197198if ( transformedBytes != null ) {199someoneTouchedTheBytecode = true;200bufferToUse = transformedBytes;201}202}203204// if someone modified it, return the modified buffer.205// otherwise return null to mean "no transforms occurred"206byte [] result;207if ( someoneTouchedTheBytecode ) {208result = bufferToUse;209}210else {211result = null;212}213214return result;215}216217218int219getTransformerCount() {220TransformerInfo[] transformerList = getSnapshotTransformerList();221return transformerList.length;222}223224boolean225setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {226TransformerInfo[] transformerList = getSnapshotTransformerList();227228for ( int x = 0; x < transformerList.length; x++ ) {229TransformerInfo transformerInfo = transformerList[x];230ClassFileTransformer aTransformer = transformerInfo.transformer();231232if ( aTransformer == transformer ) {233transformerInfo.setPrefix(prefix);234return true;235}236}237return false;238}239240241String[]242getNativeMethodPrefixes() {243TransformerInfo[] transformerList = getSnapshotTransformerList();244String[] prefixes = new String[transformerList.length];245246for ( int x = 0; x < transformerList.length; x++ ) {247TransformerInfo transformerInfo = transformerList[x];248prefixes[x] = transformerInfo.getPrefix();249}250return prefixes;251}252}253254255