All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springsource.loaded.agent.GroovyPlugin Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2010-2012 VMware and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springsource.loaded.agent;

import java.security.ProtectionDomain;

import org.objectweb.asm.ClassReader;
import org.springsource.loaded.LoadtimeInstrumentationPlugin;
import org.springsource.loaded.ReloadEventProcessorPlugin;


/**
 * What does it do?
 * 

* So far the GroovyPlugin can do two different things - configurable through the 'allowCompilableCallSites' flag. * *

* If the flag is false: The plugin intercepts two of the main system types in groovy and turns OFF call site * compilation. Without this compilation the compiler will not be generating classes, it will instead be using * reflection all the time. This is simpler to handle (as we intercept reflection) but performance == thesuck. *

* If the flag is true: The plugin leaves groovy to compile call sites. We intercept the define method in the * classloader used to define these generated call site classes and ensure they are rewritten correctly. Note there is * an alternative here of getting the SpringLoadedPreProcessor to recognize these special classloaders and just * instrument them that way. However, if we let the plugin do it it is easier to test! *

* To see the difference in these approaches, check the numbers in the Groovy Benchmark tests. * * @author Andy Clement * @since 0.7.0 */ public class GroovyPlugin implements LoadtimeInstrumentationPlugin, ReloadEventProcessorPlugin { boolean allowCompilableCallSites = true; // GroovySunClassLoader - can make the final field non final so it can be set to null (it is checked as part of the isCompilable methodin the callsitegenerator) // CallSiteGenerator - make isCompilable return false, which means we will never generate a direct call to a method that may not yet be on the target // implementing LoadtimeInstrumentationPlugin public boolean accept(String slashedTypeName, ClassLoader classLoader, ProtectionDomain protectionDomain, byte[] bytes) { // TODO take classloader into account? if (slashedTypeName == null) { return false; } if (!allowCompilableCallSites) { return slashedTypeName.equals("org/codehaus/groovy/runtime/callsite/GroovySunClassLoader") || slashedTypeName.equals("org/codehaus/groovy/runtime/callsite/CallSiteGenerator"); } else { if (slashedTypeName.equals("org/codehaus/groovy/reflection/ClassLoaderForClassArtifacts")) { return true; } } return false; } public byte[] modify(String slashedClassName, ClassLoader classLoader, byte[] bytes) { if (allowCompilableCallSites) { return modifyDefineInClassLoaderForClassArtifacts(bytes); } else { // Deactivate compilation if (slashedClassName.equals("org/codehaus/groovy/runtime/callsite/GroovySunClassLoader")) { // if (GlobalConfiguration.isRuntimeLogging && log.isLoggable(Level.INFO)) { // log.info("loadtime modifying " + slashedClassName); // } ClassReader cr = new ClassReader(bytes); NonFinalizer ca = new NonFinalizer("sunVM"); // ClassVisitingConstructorAppender ca = new ClassVisitingConstructorAppender("org/springsource/loaded/agent/SpringPlugin", // "recordInstance"); cr.accept(ca, 0); byte[] newbytes = ca.getBytes(); return newbytes; } else { // must be the CallSiteGenerator ClassReader cr = new ClassReader(bytes); FalseReturner ca = new FalseReturner("isCompilable"); cr.accept(ca, 0); byte[] newbytes = ca.getBytes(); return newbytes; } } } private byte[] modifyDefineInClassLoaderForClassArtifacts(byte[] bytes) { ClassReader cr = new ClassReader(bytes); ModifyDefineInClassLoaderForClassArtifactsType ca = new ModifyDefineInClassLoaderForClassArtifactsType(); cr.accept(ca, 0); byte[] newbytes = ca.getBytes(); return newbytes; } // called by the modified code public static void recordInstance(Object obj) { } // implementing CallbackPlugin public void reloadEvent(String typename, Class clazz, String versionsuffix) { } public boolean shouldRerunStaticInitializer(String typename, Class clazz, String encodedTimestamp) { return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy