Path: blob/master/test/jdk/java/lang/instrument/ATransformerManagementTestCase.java
41152 views
/*1* Copyright (c) 2003, 2021, 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.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/222324import java.io.*;25import java.lang.instrument.*;26import java.security.ProtectionDomain;27import java.util.*;282930/**31* Simple tests for the TransformerManager32*33*/34public abstract class35ATransformerManagementTestCase36extends AInstrumentationTestCase37{38private static final String redefinedClassName = "DummyClass";3940protected int kModSamples = 2;41public final ClassFileTransformer[] kTransformerSamples = new ClassFileTransformer[]42{43new MyClassFileTransformer( Integer.toString(0)),44new MyClassFileTransformer( Integer.toString(1)),45new MyClassFileTransformer( Integer.toString(2)),46new MyClassFileTransformer( Integer.toString(3)),47new MyClassFileTransformer( Integer.toString(4)),48new MyClassFileTransformer( Integer.toString(5)),49new MyClassFileTransformer( Integer.toString(6)),50new MyClassFileTransformer( Integer.toString(7)),51new MyClassFileTransformer( Integer.toString(8)),52new MyClassFileTransformer( Integer.toString(9)),53new MyClassFileTransformer( Integer.toString(10)),54new MyClassFileTransformer( Integer.toString(11)),55new MyClassFileTransformer( Integer.toString(12)),56new MyClassFileTransformer( Integer.toString(13)),57new MyClassFileTransformer( Integer.toString(14)),58new MyClassFileTransformer( Integer.toString(15)),59new MyClassFileTransformer( Integer.toString(16)),60new MyClassFileTransformer( Integer.toString(17)),61new MyClassFileTransformer( Integer.toString(18)),62};6364private ArrayList fTransformers; // The list of transformers65private int fTransformerIndex; // The number of transformers encountered66private String fDelayedFailure; // Set non-null if failed in transformer676869/**70* Constructor for ATransformerManagementTestCase.71*/72public ATransformerManagementTestCase(String name)73{74super(name);75}767778/**79* Returns one of the sample transformers80* @return a random transformer81*/82protected ClassFileTransformer83getRandomTransformer()84{85int randIndex = (int)Math.floor(Math.random() * kTransformerSamples.length);86verbosePrint("Choosing random transformer #" + randIndex);87return kTransformerSamples[randIndex];88}8990/**91* Method addTransformerToManager.92* @param manager93* @param transformer94*/95protected void96addTransformerToManager(97Instrumentation manager,98ClassFileTransformer transformer)99{100addTransformerToManager(manager, transformer, false);101}102103/**104* Method addTransformerToManager.105* @param manager106* @param transformer107* @param canRetransform108*/109protected void110addTransformerToManager(111Instrumentation manager,112ClassFileTransformer transformer,113boolean canRetransform)114{115if (transformer != null)116{117fTransformers.add(transformer);118}119// workaroud for JDK-8264667: create log message before addTransformer()120String msg = "Added transformer " + transformer121+ " with canRetransform=" + canRetransform;122manager.addTransformer(transformer, canRetransform);123verbosePrint(msg);124}125126/**127* Remove transformer from manager and list128* @param manager129* @param transformer130*/131protected void132removeTransformerFromManager(133Instrumentation manager,134ClassFileTransformer transformer)135{136assertTrue("Transformer not found in manager ("+transformer+")", manager.removeTransformer(transformer));137138if (transformer != null)139{140fTransformers.remove(transformer);141}142verbosePrint("Removed transformer " + transformer);143}144145/**146* Decrements the transformer index as well as removes transformer147* @param fInst manager148* @param transformer transformer to remove149* @param decrementIndex the tranformer index gets out of sync with transformers150* that are removed from the manager151*/152protected void153removeTransformerFromManager( Instrumentation manager,154ClassFileTransformer transformer,155boolean decrementIndex)156{157removeTransformerFromManager(manager, transformer);158if (decrementIndex)159{160fTransformerIndex--;161verbosePrint("removeTransformerFromManager fTransformerIndex decremented to: " +162fTransformerIndex);163}164}165166/**167* verify transformer by asserting that the number of transforms that occured168* is the same as the number of valid transformers added to the list.169* @param manager170*/171protected void172verifyTransformers(Instrumentation manager)173{174File f = new File(System.getProperty("test.classes", "."), redefinedClassName + ".class");175System.out.println("Reading test class from " + f);176try177{178InputStream redefineStream = new FileInputStream(f);179byte[] bytes = NamedBuffer.loadBufferFromStream(redefineStream);180ClassDefinition cd = new ClassDefinition(DummyClass.class, bytes);181fInst.redefineClasses(new ClassDefinition[]{ cd });182verbosePrint("verifyTransformers redefined " + redefinedClassName);183}184catch (IOException e)185{186fail("Could not load the class: " + redefinedClassName);187}188catch (ClassNotFoundException e)189{190fail("Could not find the class: " + redefinedClassName);191}192catch (UnmodifiableClassException e)193{194fail("Could not modify the class: " + redefinedClassName);195}196197// Report any delayed failures198assertTrue(fDelayedFailure, fDelayedFailure == null);199200assertEquals("The number of transformers that were run does not match the expected number added to manager",201fTransformers.size(), fTransformerIndex);202}203204205/**206* Asserts that the transformer being checked by the manager is the correct207* one (as far as order goes) and updates the number of transformers that have208* been called. Note that since this is being called inside of a transformer,209* a standard assert (which throws an exception) cannot be used since it would210* simply cancel the transformation and otherwise be ignored. Instead, note211* the failure for delayed processing.212* @param ClassFileTransformer213*/214private void215checkInTransformer(ClassFileTransformer transformer)216{217verbosePrint("checkInTransformer: " + transformer);218if (fDelayedFailure == null)219{220if (fTransformers.size() <= fTransformerIndex)221{222String msg = "The number of transformers that have checked in (" +(fTransformerIndex+1) +223") is greater number of tranformers created ("+fTransformers.size()+")";224fDelayedFailure = msg;225System.err.println("Delayed failure: " + msg);226verbosePrint("Delayed failure: " + msg);227}228if (!fTransformers.get(fTransformerIndex).equals(transformer))229{230String msg = "Transformer " + fTransformers.get(fTransformerIndex) +231" should be the same as " + transformer;232fDelayedFailure = msg;233System.err.println("Delayed failure: " + msg);234verbosePrint("Delayed failure: " + msg);235}236fTransformerIndex++;237verbosePrint("fTransformerIndex incremented to: " + fTransformerIndex);238}239}240241/**242* Create a new manager, a new transformer list, and initializes the number of transformers243* indexed to zero.244*/245protected void246setUp()247throws Exception248{249super.setUp();250fTransformers = new ArrayList();251fTransformerIndex = 0;252fDelayedFailure = null;253verbosePrint("setUp completed");254}255256/**257* Sets the manager and transformers to null so that setUp needs to update.258*/259protected void260tearDown()261throws Exception262{263verbosePrint("tearDown beginning");264fTransformers = null;265super.tearDown();266}267268/*269* Simple transformer that registers when it transforms270*/271public class MyClassFileTransformer extends SimpleIdentityTransformer {272private final String fID;273274public MyClassFileTransformer(String id) {275super();276fID = id;277}278279public String toString() {280return MyClassFileTransformer.this.getClass().getName() + fID;281}282283public byte[]284transform(285ClassLoader loader,286String className,287Class<?> classBeingRedefined,288ProtectionDomain protectionDomain,289byte[] classfileBuffer) {290291// The transform testing is triggered by redefine, ignore others292if (classBeingRedefined != null) checkInTransformer(MyClassFileTransformer.this);293294return super.transform( loader,295className,296classBeingRedefined,297protectionDomain,298classfileBuffer);299}300301public byte[]302transform(303Module module,304ClassLoader loader,305String className,306Class<?> classBeingRedefined,307ProtectionDomain protectionDomain,308byte[] classfileBuffer) {309310// The transform testing is triggered by redefine, ignore others311if (classBeingRedefined != null) checkInTransformer(MyClassFileTransformer.this);312313return super.transform( module,314loader,315className,316classBeingRedefined,317protectionDomain,318classfileBuffer);319}320}321322323/**324* Class loader that does nothing325*/326public class MyClassLoader extends ClassLoader327{328/**329* Constructor for MyClassLoader.330*/331public MyClassLoader()332{333super();334}335336}337338public String debug_byteArrayToString(byte[] b) {339if (b == null) return "null";340341StringBuffer buf = new StringBuffer();342buf.append("byte[");343buf.append(b.length);344buf.append("] (");345for (int i = 0; i < b.length; i++)346{347buf.append(b[i]);348buf.append(",");349}350buf.deleteCharAt(buf.length()-1);351buf.append(")");352353return buf.toString();354}355}356357358