Java tutorial
/* * Copyright 2014-2016 JKOOL, LLC. * * This file is part of TNT4J-Streams-Zorka. * * TNT4J-Streams-Zorka is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * TNT4J-Streams-Zorka is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with TNT4J-Streams-Zorka. If not, see <http://www.gnu.org/licenses/>. */ package com.jkoolcloud.tnt4j.streams.utils; import java.io.File; import java.lang.instrument.Instrumentation; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.List; import org.apache.commons.io.filefilter.WildcardFileFilter; import com.jitlogic.zorka.agent.AgentMain; import com.jkoolcloud.tnt4j.core.OpLevel; import com.jkoolcloud.tnt4j.sink.DefaultEventSinkFactory; import com.jkoolcloud.tnt4j.sink.EventSink; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; /** * Wrapper for Zorka main class to automatically attach to running Java VM's. As Zorka doesn't come with agentmain * feature having class it could't be loaded by VirtualMachine.loadAgent(). This class appends required libraries to * attaching JVM classpath and loads Zorka as Java agent. * * @version $Revision: 1 $ */ public final class ZorkaAttach { private static final EventSink LOGGER = DefaultEventSinkFactory.defaultEventSink(ZorkaAttach.class); private ZorkaAttach() { } /** * Main entry point for attaching Zorka agent to running JVM. * * @param args * command-line arguments. Supported arguments: * <table summary="TNT4J-Streams agent command line arguments"> * <tr> * <td> </td> * <td> zorkaAgentPath</td> * <td>(required) Zorka agent path</td> * </tr> * <tr> * <td> </td> * <td> VMNameToAttachTo</td> * <td>(required) Java VM name to attach to</td> * </tr> * </table> */ public static void main(String... args) { LOGGER.log(OpLevel.DEBUG, StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.starting.main")); if (args.length != 2) { System.out.println( StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.main.usage")); return; } List<VirtualMachineDescriptor> runningVMsList = VirtualMachine.list(); boolean found = false; // args[0] - agent path to attach // args[1] - VM name to attach to for (VirtualMachineDescriptor rVM : runningVMsList) { if (rVM.displayName().contains(args[1]) && !rVM.displayName().contains(ZorkaAttach.class.getSimpleName())) { try { VirtualMachine vm = VirtualMachine.attach(rVM.id()); File pathFile = new File( ZorkaAttach.class.getProtectionDomain().getCodeSource().getLocation().getPath()); String agentPath = pathFile.getAbsolutePath(); LOGGER.log(OpLevel.INFO, StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.attaching.agent"), agentPath, rVM.displayName()); vm.loadAgent(agentPath, args[0]); vm.detach(); } catch (Exception e) { throw new RuntimeException(e); } found = true; } } if (!found) { System.out.println(StreamsResources.getStringFormatted(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.no.jvm", args[0])); System.out.println( StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.available.jvms")); System.out.println( StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.list.begin")); for (VirtualMachineDescriptor vmD : runningVMsList) { System.out.println(vmD.displayName()); } System.out.println( StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.list.end")); } } /** * Entry point for loading Zorka as java agent. * * @param zorkaHomePath * Zorka home dir path * @param inst * JVM instrumentation * @throws Exception * if exception occurs while loading java agent * * @see AgentMain#premain(String, Instrumentation) */ public static void agentmain(final String zorkaHomePath, final Instrumentation inst) throws Exception { final String zorkaDirPath = new File(zorkaHomePath).getAbsolutePath(); System.setProperty("zorka.home.dir", zorkaDirPath); LOGGER.log(OpLevel.DEBUG, StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.zorka.path"), zorkaDirPath); File zorkaPath = new File(zorkaDirPath); final String[] classPathEntries = zorkaPath.list(new WildcardFileFilter("*.jar")); // NON-NLS if (classPathEntries != null) { for (String classPathEntry : classPathEntries) { File pathFile = new File(classPathEntry); extendClasspath(pathFile.toURI().toURL()); } } AgentMain.premain(null, inst); } /** * Loads required classpath entries to running JVM. * * @param classPathEntriesURL * classpath entries URLs to attach to JVM * @throws Exception * if exception occurs while extending system class loader's classpath */ private static void extendClasspath(URL... classPathEntriesURL) throws Exception { URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); method.setAccessible(true); for (URL classPathEntryURL : classPathEntriesURL) { try { method.invoke(classLoader, classPathEntryURL); } catch (Exception e) { LOGGER.log(OpLevel.ERROR, StreamsResources.getString(ZorkaConstants.RESOURCE_BUNDLE_NAME, "ZorkaAttach.could.not.load"), classPathEntryURL, e); } } } }