public class MainClass { private static Instrumentation instrumentation; // , System.currentTimeMillis private static ClassTransformer transformer; // ClassFileTransformer public static File FILE = null; // , public static void premain(String args, Instrumentation inst) throws Exception { System.out.println("dateshift agent starting"); if (args != null && args.length() > 0) { // , String path = args; System.out.println("Using dateshift.txt path from args: '" + path + "'"); FILE = new File(path); } else { // , - dateshift.txt, bin tomcat-a FILE = new File(new File(System.getenv("CATALINA_HOME"), "bin"), "dateshift.txt"); } System.out.println("Path for dateshift.txt: '" + FILE.getAbsolutePath() + "'"); instrumentation = inst; // , JVM transformer = new ClassTransformer(); instrumentation.addTransformer(transformer, true); // , ClassTransformer Class[] classes = inst.getAllLoadedClasses(); // , . , , ArrayList<Class> classList = new ArrayList<Class>(); for (int i = 0; i < classes.length; i++) { if (inst.isModifiableClass(classes[i])) { // , classList.add(classes[i]); } } // Reload classes, if possible. Class[] workaround = new Class[classList.size()]; try { inst.retransformClasses(classList.toArray(workaround)); // } catch (UnmodifiableClassException e) { System.err.println("MainClass was unable to retransform early loaded classes: " + e); } } }
public class ClassTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if(className.startsWith("ru/javaorca/")) return null; // try { ClassPool pool = ClassPool.getDefault(); CtClass s1 = pool.get("java.lang.System"); CtMethod m11 = s1.getDeclaredMethod("currentTimeMillis"); // , CtClass s2 = pool.get("ru.javaorca.MySystem"); CtMethod m21 = s2.getDeclaredMethod("currentTimeMillis"); // , CodeConverter cc = new CodeConverter(); cc.redirectMethodCall(m11, m21); // CtClass cl = pool.makeClass(new ByteArrayInputStream(classfileBuffer), false); // , if(cl.isFrozen()) return null; CtConstructor[] constructors = cl.getConstructors(); // for(CtConstructor constructor : constructors) { constructor.instrument(cc); // } CtMethod[] methods = cl.getDeclaredMethods(); // for(CtMethod method : methods) { method.instrument(cc); // } classfileBuffer = cl.toBytecode(); } catch (Exception ex) { System.out.println("Exception: " + ex); ex.printStackTrace(); } return classfileBuffer; // } }
public class MySystem { public static long currentTimeMillis() { long res = System.currentTimeMillis(); // long res1 = DateShift.getTime(res); // return res1; // } }
public class DateShift { private static volatile long lastModified = 0; // private static volatile long timeShift = 0; // private static final long timeFilter = 86400000L; // 1000*60*60*24, public static long getTime(long currentTime) { // , long res = currentTime; if ((lastModified > 0 && !MainClass.FILE.exists()) || lastModified < MainClass.FILE.lastModified()) { // , System.out.println("File modification detected"); synchronized (MainClass.FILE) { if (MainClass.FILE.exists()) { lastModified = MainClass.FILE.lastModified(); long newTime = readDateFromFile(); // if (newTime > 0) { timeShift = newTime - ((res / timeFilter) * timeFilter); // } } else { lastModified = 0; // , timeShift = 0; } } } if (timeShift != 0) { res += timeShift; // } return res; } private static long readDateFromFile() { // , System.out.println("Reading data from file '" + MainClass.FILE.getAbsolutePath() + "'"); long res = 0; BufferedReader br = null; try { br = new BufferedReader(new FileReader(MainClass.FILE)); String line = br.readLine(); // if (line != null && !line.trim().isEmpty()) { SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT); // dd.MM.yyyy try { Date date = DATE_FORMAT.parse(line); System.out.println("Loaded date from file: " + date); Calendar c = Calendar.getInstance(); c.setTime(date); long offset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET); // . , JVM System.out.println("Offset: " + offset); res = c.getTime().getTime(); res += offset; } catch (ParseException e) { System.out.println("ParseException: " + e); e.printStackTrace(System.out); } } else { System.out.println("File is empty"); } } catch (IOException e) { System.out.println("IOException: " + e); e.printStackTrace(System.out); } finally { if (br != null) { try { br.close(); } catch (IOException e) { System.out.println("IOException: " + e); e.printStackTrace(System.out); } } } return res; } }
-javaagent:D:\development\srv\dateshift-1.4-jar-with-dependencies.jar=D:\development\srv\dateshift.txt
Source: https://habr.com/ru/post/170401/
All Articles