001 package railo.runtime.instrumentation; 002 003 import java.lang.instrument.Instrumentation; 004 import java.lang.management.ManagementFactory; 005 import java.lang.management.RuntimeMXBean; 006 import java.lang.reflect.Field; 007 import java.lang.reflect.InvocationTargetException; 008 import java.lang.reflect.Method; 009 010 import org.objectweb.asm.ClassReader; 011 012 import railo.commons.io.SystemUtil; 013 import railo.commons.io.res.Resource; 014 import railo.commons.io.res.ResourcesImpl; 015 import railo.commons.lang.ClassUtil; 016 import railo.commons.lang.SystemOut; 017 import sun.management.VMManagement; 018 019 public class InstrumentationFactory { 020 021 private static Instrumentation inst; 022 private static boolean doInit=true; 023 024 public static synchronized Instrumentation getInstance() { 025 if(doInit) { 026 doInit=false; 027 028 Class agent = ClassUtil.loadClass("railo.runtime.instrumentation.Agent",null); 029 if(agent==null) { 030 SystemOut.printDate("missing class railo.runtime.instrumentation.Agent"); 031 return null; 032 } 033 034 // if Agent was loaded at startup there is already a Instrumentation 035 inst=getInstrumentation(agent); 036 037 // try to load Agent 038 if(inst==null) { 039 SystemOut.printDate("class railo.runtime.instrumentation.Agent.getInstrumentation() is not returning a Instrumentation"); 040 try { 041 String id=getPid(); 042 String path=getResourcFromLib().getAbsolutePath(); 043 044 Class vmClass = ClassUtil.loadClass("com.sun.tools.attach.VirtualMachine"); 045 Object vmObj=attach(vmClass,id); 046 loadAgent(vmClass,vmObj,path); 047 detach(vmClass,vmObj); 048 } 049 catch (Throwable t) { 050 //t.printStackTrace(); 051 return null; 052 } 053 inst=getInstrumentation(agent); 054 } 055 056 if(inst!=null)SystemOut.printDate("java.lang.instrument.Instrumentation is used to reload class files"); 057 058 } 059 return inst; 060 } 061 062 private static Instrumentation getInstrumentation(Class agent) { 063 try { 064 Method getInstrumentation = agent.getMethod("getInstrumentation", new Class[0]); 065 return (Instrumentation) getInstrumentation.invoke(null, new Object[0]); 066 } 067 catch (Throwable t) { 068 t.printStackTrace(); 069 return null; 070 } 071 } 072 073 private static Object attach(Class vmClass, String id) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 074 Method attach = vmClass.getMethod("attach", new Class[]{String.class}); 075 return attach.invoke(null, new Object[]{id}); 076 } 077 078 private static void loadAgent(Class vmClass, Object vmObj, String path) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 079 Method loadAgent = vmClass.getMethod("loadAgent", new Class[]{String.class}); 080 loadAgent.invoke(vmObj, new Object[]{path}); 081 } 082 083 private static void detach(Class vmClass, Object vmObj) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 084 Method detach = vmClass.getMethod("detach", new Class[]{}); 085 detach.invoke(vmObj, new Object[]{}); 086 } 087 088 private static Resource getResourcFromLib() { 089 Resource[] pathes = SystemUtil.getClassPathes(); 090 Resource res = null; 091 String name=null; 092 if(pathes!=null)for(int i=0;i<pathes.length;i++){ 093 name=pathes[i].getName(); 094 if(name.equalsIgnoreCase("railo-instrumentation.jar") || name.equalsIgnoreCase("railo-inst.jar")) { 095 res=pathes[i]; 096 break; 097 } 098 } 099 100 if(res==null) { 101 Class agent = ClassUtil.loadClass("railo.runtime.instrumentation.Agent",null); 102 if(agent!=null)res=getResourcFromLib(agent); 103 else res=getResourcFromLib(ClassReader.class); 104 105 } 106 return res; 107 } 108 109 private static Resource getResourcFromLib(Class clazz) { 110 String path=clazz.getClassLoader().getResource(".").getFile(); 111 Resource dir = ResourcesImpl.getFileResourceProvider().getResource(path); 112 Resource res = dir.getRealResource("railo-instrumentation.jar"); 113 if(!res.exists())res=dir.getRealResource("railo-inst.jar"); 114 if(!res.exists())res=null; 115 return res; 116 } 117 private static String getPid() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { 118 RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean(); 119 Field jvmField = mxbean.getClass().getDeclaredField("jvm"); 120 121 jvmField.setAccessible(true); 122 VMManagement management = (VMManagement) jvmField.get(mxbean); 123 Method method = management.getClass().getDeclaredMethod("getProcessId"); 124 method.setAccessible(true); 125 Integer processId = (Integer) method.invoke(management); 126 127 return processId.toString(); 128 } 129 }