这里我写了个简单的实现:

  (注:这里的 depth 并不是递归深度,而是递归次数,当时搞错了)

  好了,现在我们来验证一下我们的结果,通过看jdk源码,我们知道,.* 在匹配时调用的是java/util/regex/Pattern$CharProperty.match 方法,而 D 调用的是java/util/regex/Pattern$BmpCharProperty.match 。由于我们不能更改源代码,我们使用ASM

  字节注入工具,分别在这两个方法上埋点,部分代码如下:

  package com.alibaba.taobao.tinyprofiler;

  import java.lang.instrument.ClassFileTransformer;

  import java.lang.instrument.IllegalClassFormatException;

  import java.security.ProtectionDomain;

  import org.objectweb.asm.ClassAdapter;

   import org.objectweb.asm.ClassReader;

  import org.objectweb.asm.ClassWriter;

  public class MethodCallCountTransformer implements ClassFileTransformer {

  @Override

  public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,

  ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

  try {

  if (!“java/util/regex/Pattern$CharProperty”.equals(className)

  && !“java/util/regex/Pattern$BmpCharProperty”.equals(className)) {

  return classfileBuffer;

  }

  ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);

  ClassAdapter adapter = new MethodCallClassAdapter(writer, className);

  ClassReader reader = new ClassReader(classfileBuffer);

  reader.accept(adapter, 0);

  // 生成新类字节码

  return writer.toByteArray();

  } catch (Exception e) {

  e.printStackTrace();

  // 返回旧类字节码

  return classfileBuffer;

  }

  }

  }

  package com.alibaba.taobao.tinyprofiler;

  import java.util.concurrent.atomic.AtomicInteger;

  public class Counter {

  private static AtomicInteger methodCallCount = new AtomicInteger(0);

  public static void printAndIncCount(String className, String methodName) {

  System.out.println(className + “.” + methodName + “ called, total times ” + methodCallCount.incrementAndGet());

  }

  }

  OK,现在我们输入:

  String regex = “.*.*.*D”;

  String target = “22asdvasdx”;

  Pattern.compile(regex).matcher(target).matches();

  System.out.println(“Xuanyin’s estimated count: ” + findTotalWays(4, target.length()) + “; depth: ” + recursionDepth);

  输出结果(注:这里的 depth 并不是递归深度,而是递归次数,当时搞错了):

  肿么样,分毫不差~OK,那么我们现在回到开始的问题,输入 .*.*.*.*.*.*D 去匹配 com.taobao.binary.bogda.query.service.RulesInfoQueryService:1.0.0.daily

  结果显示需要 5 亿 匹配, 还要进出栈近 2.5 亿次哦

  这里我的机器是i7-2600K 超4.5G,结果显示需要5秒,这还是不是差的情况哦~

  而每次用户查询要匹配近600个这样的字符串,~你说匹配得完嘛