Currently Bytecode Instrumentation is done using preprocessing. Original classes are not changed. Jour based on bytecode instrumentation by javassist.
Different types of instrumentation could be created. Use jour.xml to configure the type of instrumentation you want.
net.sf.jour.PreProcessor -dst outDir (-src targetDir | -classlist fileName.txt) [-imap mapFileName]
This file is used to define what kind of instrumentation would be applied and to which classes and methods.
The best way is to start with examples:
<jour> <aspect type="net.sf.jour.instrumentor.ProfilerInstrumentor"> <typedef> com.solect.* </typedef> <pointcut expr="* execSql*(..)"/> </aspect> </jour>
This will instrument all classes that have functions like execSql.
Consider original code.
package com.solect.iaf; import java.sql.*; public class DBClientExample { String connectionUrl = "jdbc:subprotocol:subname"; public void execSqlUpdate(String sql) throws Exception { Connection conn = DriverManager.getConnection(connectionUrl); Statement stmt = conn.createStatement(); stmt.close(); conn.close(); } }
This is how the code will look after instrumentation and decompilation
package com.solect.iaf; import java.sql.*; import net.sf.jour.rt.agent.*; public class DBClientExample { String connectionUrl; public DBClientExample() { connectionUrl = "jdbc:subprotocol:subname"; } public void execSqlUpdate(String sql) throws Exception { if (Elog.ON) { Elog.logEvent(new ProfilerEvent(ProfilerEvent.START, 1, null)); } try { Connection conn = DriverManager.getConnection(connectionUrl); Statement stmt = conn.createStatement(); stmt.close(); conn.close(); if (Elog.ON) { Elog.logEvent(new ProfilerEvent(ProfilerEvent.END, 1, null)); } } catch (Throwable throwable1) { if (Elog.ON) { Elog.logEvent(new ProfilerEvent(ProfilerEvent.END, 1, throwable1))); } throw throwable1; } } }
File jourInstrumentationMap.txt
would contain one line.
It would be used to map the number 1 to the class and method name.
1;com.solect.iaf.DBClientExample|execSqlUpdate|(Ljava/lang/String;)V