/**
* Copyright 2014 SAP AG
*
* 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.aim.mainagent.instrumentor;
import java.lang.instrument.ClassDefinition;
import java.util.Map;
import org.aim.api.exceptions.InstrumentationException;
import org.aim.logging.AIMLogger;
import org.aim.logging.AIMLoggerFactory;
/**
* Responsible for swapping bytecode.
*
* @author Alexander Wert
*
*/
public final class JAgentSwapper implements BCSwapper {
private static final AIMLogger LOGGER = AIMLoggerFactory.getLogger(JAgentSwapper.class);
private static JAgentSwapper instance;
/**
* Returns singleton instance.
*
* @return singleton
* @throws InstrumentationException
* if Java Instrumentation instance has never been set
*/
public static synchronized JAgentSwapper getInstance() throws InstrumentationException {
if (instance == null) {
instance = new JAgentSwapper();
}
return instance;
}
private JAgentSwapper() throws InstrumentationException {
if (JInstrumentation.getInstance().getjInstrumentation() == null) {
throw new RuntimeException("Java Instrumentation instance has never been set!");
}
}
/**
* Swaps the bytecode of the given classes.
*
* @param newByteCodes
* mapping from classes to new bytecodes to swap
*/
public void redefineClasses(Map<Class<?>, byte[]> newByteCodes) {
int i = 0;
for (Class<?> clazz : newByteCodes.keySet()) {
try {
ClassDefinition cd = new ClassDefinition(clazz, newByteCodes.get(clazz));
LOGGER.debug("Going to redefined class: {}", clazz.getName());
ClassDefinition[] cdArray = new ClassDefinition[1];
cdArray[0] = cd;
JInstrumentation.getInstance().getjInstrumentation().redefineClasses(cdArray);
i++;
} catch (Throwable e) {
LOGGER.error("Error: {}", e);
}
}
if (i > 0) {
LOGGER.info("Redefined {} classes!", i);
}
}
}