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 // try to load Agent 037 if(inst==null) { 038 try { 039 040 String id=getPid(); 041 String path=getResourcFromLib().getAbsolutePath(); 042 043 Class vmClass = ClassUtil.loadClass("com.sun.tools.attach.VirtualMachine"); 044 Object vmObj=attach(vmClass,id); 045 loadAgent(vmClass,vmObj,path); 046 detach(vmClass,vmObj); 047 } 048 catch (Throwable t) { 049 t.printStackTrace(); 050 return null; 051 } 052 inst=getInstrumentation(agent); 053 } 054 055 if(inst!=null)SystemOut.printDate("java.lang.instrument.Instrumentation is used to reload class files"); 056 057 } 058 return inst; 059 } 060 061 private static Instrumentation getInstrumentation(Class agent) { 062 try { 063 Method getInstrumentation = agent.getMethod("getInstrumentation", new Class[0]); 064 return (Instrumentation) getInstrumentation.invoke(null, new Object[0]); 065 } 066 catch (Throwable t) { 067 t.printStackTrace(); 068 return null; 069 } 070 } 071 072 private static Object attach(Class vmClass, String id) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 073 Method attach = vmClass.getMethod("attach", new Class[]{String.class}); 074 return attach.invoke(null, new Object[]{id}); 075 } 076 077 private static void loadAgent(Class vmClass, Object vmObj, String path) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 078 Method loadAgent = vmClass.getMethod("loadAgent", new Class[]{String.class}); 079 loadAgent.invoke(vmObj, new Object[]{path}); 080 } 081 082 private static void detach(Class vmClass, Object vmObj) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { 083 Method detach = vmClass.getMethod("detach", new Class[]{}); 084 detach.invoke(vmObj, new Object[]{}); 085 } 086 087 private static Resource getResourcFromLib() { 088 Resource[] pathes = SystemUtil.getClassPathes(); 089 Resource res = null; 090 String name=null; 091 if(pathes!=null)for(int i=0;i<pathes.length;i++){ 092 name=pathes[i].getName(); 093 if(name.equalsIgnoreCase("railo-instrumentation.jar") || name.equalsIgnoreCase("railo-inst.jar")) { 094 res=pathes[i]; 095 break; 096 } 097 } 098 099 if(res==null) { 100 Class agent = ClassUtil.loadClass("railo.runtime.instrumentation.Agent",null); 101 if(agent!=null)res=getResourcFromLib(agent); 102 else res=getResourcFromLib(ClassReader.class); 103 104 } 105 return res; 106 } 107 108 private static Resource getResourcFromLib(Class clazz) { 109 String path=clazz.getClassLoader().getResource(".").getFile(); 110 Resource dir = ResourcesImpl.getFileResourceProvider().getResource(path); 111 Resource res = dir.getRealResource("railo-instrumentation.jar"); 112 if(!res.exists())res=dir.getRealResource("railo-inst.jar"); 113 if(!res.exists())res=null; 114 return res; 115 } 116 private static String getPid() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { 117 RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean(); 118 Field jvmField = mxbean.getClass().getDeclaredField("jvm"); 119 120 jvmField.setAccessible(true); 121 VMManagement management = (VMManagement) jvmField.get(mxbean); 122 Method method = management.getClass().getDeclaredMethod("getProcessId"); 123 method.setAccessible(true); 124 Integer processId = (Integer) method.invoke(management); 125 126 return processId.toString(); 127 } 128 }