-
-
Save FlyingFish07/b155d5fffe34c2c06413ed63922240a0 to your computer and use it in GitHub Desktop.
Fake time java agent
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.zyh.ftmagent; | |
| import java.lang.instrument.Instrumentation; | |
| import java.lang.instrument.UnmodifiableClassException; | |
| public class FtmAgent { | |
| public static void premain(String agentArgs, Instrumentation inst) | |
| throws ClassNotFoundException, UnmodifiableClassException{ | |
| inst.addTransformer(new TimeTransformer()); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Manifest-Version: 1.0 | |
| Premain-Class: com.zyh.ftmagent.FtmAgent | |
| Boot-Class-Path: javassist-3.22.0-CR1.jar |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.zyh.ftmagent; | |
| import java.util.Date; | |
| public class MyDate extends Date { | |
| private static final long serialVersionUID = 1L; | |
| public MyDate(){ | |
| super(MySystemTime.currentTimeMillis()); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.zyh.ftmagent; | |
| public class MySystemTime { | |
| //默认为当前时间 | |
| private static final Long INIT_VALUE = 0l; | |
| private static ThreadLocal<Long> timeDiff = new ThreadLocal<Long>() { | |
| @Override | |
| protected Long initialValue() { | |
| return INIT_VALUE; | |
| } | |
| }; | |
| public static long currentTimeMillis() { | |
| return System.currentTimeMillis() - timeDiff.get(); | |
| } | |
| public static long nanoTime() { | |
| return System.nanoTime() - timeDiff.get() * 1000; | |
| } | |
| /** | |
| * 设置距离当前的时间,为正表示后退多少ms | |
| * | |
| * @param diff | |
| */ | |
| public static void setTimeDiff(long diff) { | |
| timeDiff.set(diff); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.zyh.test; | |
| import java.text.SimpleDateFormat; | |
| import java.util.Date; | |
| public class MyTestClass { | |
| public void dateTest() { | |
| long stTime = System.currentTimeMillis(); | |
| System.out.println("Now CurrentTimeMillis 1:" + stTime); | |
| long nt = System.nanoTime(); | |
| System.out.println("Now nanoTime:" + nt); | |
| System.out.println("Now CurrentTImeMillis 2:" + System.currentTimeMillis()); | |
| Date ct = new Date(); | |
| SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss"); | |
| String rslt = sdf.format(ct); | |
| System.out.println("Now Date:" + rslt); | |
| System.out.println("now Date2:" + sdf.format(new Date())); | |
| Date ct2 = new Date(System.currentTimeMillis()); | |
| System.out.println("Now Date3:" + ct2); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| <modelVersion>4.0.0</modelVersion> | |
| <groupId>com.zyh</groupId> | |
| <artifactId>ftmagent</artifactId> | |
| <version>0.0.1-SNAPSHOT</version> | |
| <packaging>jar</packaging> | |
| <name>ftmagent</name> | |
| <url>http://maven.apache.org</url> | |
| <properties> | |
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
| </properties> | |
| <dependencies> | |
| <dependency> | |
| <groupId>junit</groupId> | |
| <artifactId>junit</artifactId> | |
| <version>4.12</version> | |
| <scope>test</scope> | |
| </dependency> | |
| <!-- https://mvnrepository.com/artifact/org.javassist/javassist --> | |
| <dependency> | |
| <groupId>org.javassist</groupId> | |
| <artifactId>javassist</artifactId> | |
| <version>3.22.0-CR1</version> | |
| </dependency> | |
| </dependencies> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| java -javaagent=ftm-agent.jar -jar ftm-test.jar |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.zyh.test; | |
| import java.text.SimpleDateFormat; | |
| import java.util.Date; | |
| import com.zyh.ftmagent.MySystemTime; | |
| public class TestMain { | |
| public static void main( String[] args ) throws Exception { | |
| System.out.println("Real Time:" +System.currentTimeMillis()); | |
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| System.out.println("Real Date2:" + sdf.format(new Date())); | |
| MySystemTime.setTimeDiff(3000l);//时钟回拨3s | |
| MyTestClass testClass = new MyTestClass(); | |
| testClass.dateTest(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.zyh.ftmagent; | |
| import java.lang.instrument.ClassFileTransformer; | |
| import java.lang.instrument.IllegalClassFormatException; | |
| import java.security.ProtectionDomain; | |
| import javassist.CannotCompileException; | |
| import javassist.ClassPool; | |
| import javassist.CtBehavior; | |
| import javassist.CtClass; | |
| import javassist.NotFoundException; | |
| import javassist.expr.ExprEditor; | |
| import javassist.expr.MethodCall; | |
| import javassist.expr.NewExpr; | |
| public class TimeTransformer implements ClassFileTransformer { | |
| public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, | |
| ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { | |
| // 仅对于com.zyh.test包下的类进行替换 | |
| if (className.startsWith("com/zyh/test")) { | |
| byte[] transformed = null; | |
| System.out.println("Transforming " + className); | |
| ClassPool pool = ClassPool.getDefault(); | |
| CtClass cl = null; | |
| try { | |
| cl = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer)); | |
| if (cl.isInterface() == false) { | |
| CtBehavior[] methods = cl.getDeclaredBehaviors(); | |
| for (int i = 0; i < methods.length; i++) { | |
| if (methods[i].isEmpty() == false) { | |
| doMethod(methods[i]); | |
| } | |
| } | |
| transformed = cl.toBytecode(); | |
| } | |
| } catch (Exception e) { | |
| System.err.println("Could not instrument " + className + ", exception : " + e.getMessage()); | |
| } finally { | |
| if (cl != null) { | |
| cl.detach(); | |
| } | |
| } | |
| return transformed; | |
| } | |
| return null; | |
| } | |
| private void doMethod(CtBehavior method) throws NotFoundException, CannotCompileException { | |
| // 修改方法体的定义 | |
| method.instrument(new ExprEditor() { | |
| // 修改一般的方法调用语句 | |
| public void edit(MethodCall m) throws CannotCompileException { | |
| try { | |
| if (m.getClassName().equals("java.lang.System")) { | |
| if (m.getMethodName().equals("nanoTime")) { | |
| m.replace("{long rslt = com.zyh.ftmagent.MySystemTime#nanoTime(); $_ = ($r)rslt; }"); | |
| } else if (m.getMethodName().equals("currentTimeMillis")) { | |
| m.replace( | |
| "{long rslt = com.zyh.ftmagent.MySystemTime#currentTimeMillis(); $_ = ($r)rslt; }"); | |
| } | |
| } | |
| } catch (Exception ex) { | |
| ex.printStackTrace(); | |
| throw new RuntimeException(ex); | |
| } | |
| } | |
| // 修改new Date()这种格式的代码,替换其中的class类 | |
| public void edit(NewExpr e) throws CannotCompileException { | |
| try { | |
| if (e.getClassName().equals("java.util.Date")) { | |
| e.replace("{$_ = new com.zyh.ftmagent.MyDate();}"); | |
| } | |
| } catch (Exception ex) { | |
| ex.printStackTrace(); | |
| throw new RuntimeException(ex); | |
| } | |
| } | |
| }); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment