동적 실시 간 추적 자바 프로그램

6892 단어 ASMAOPtransformBTrace
앞 에 써 있어 요. AOP 기반 로그 디 버 깅 자바 프로그램 을 추적 하 는 방법 에 대해 논 의 했 지만 완벽 하 지 는 않 았 다. 나중에 발견 되 었 다. Btrace , 동적 바이트 코드 주입 기술 을 빌려 우아 하고 기능 이 강하 기 때문이다.  다만, 사용 할 때 항상 더 듬 거 리 며 어떤 문 제 를 추적 하기 위해 많은 시간 을 들 여 Btrace 스 크 립 트 를 디 버 깅 합 니 다. 이 를 위해 저 는 몇 가지 추적 모드 를 스 크 립 트 템 플 릿 으로 경화 시 키 고 사용 할 때 정규 표현 식 과 같은 것 을 조정 하려 고 합 니 다.  추적 과정 은 흔히 가설 과 검증 의 나선형 교체 과정 입 니 다. BTrace 로 목표 프로 세 스 를 반복 적 으로 추적 하면 알 수 없 는 몇 번 의 사용 이 불가능 합 니 다. 마지막 으로 목표 프로 세 스 를 다시 시작 해 야 합 니 다. 만약 에 온라인 에서 멈 출 수 없 는 서비스 라면 이런 방식 은 믿 을 수 없 는 것 이 라 고 생각 합 니 다. 이 를 위해 자신의 사용 을 결정 하 는 것 이 간단 합 니 다.또한 목표 프로 세 스 를 다시 시작 하지 않 고 반복 적 으로 추적 하 는 도 구 를 잘 지원 할 수 있 습 니 다. AOP AOP 는 Btrace, jip 1 등 여러 모니터링 도구 의 핵심 사상 입 니 다. 코드 로 가장 쉽게 설명 할 수 있 습 니 다.
 public void say(String words){
  Trace.enter();
  System.out.println(words);
  Trace.exit();
}
예 를 들 어 Trace. enter () 와 Trace. exit () 는 say (words) 안의 코드 를 둘러싸 고 방법 을 출입 하 는 것 을 단면 적 으로 처리 하면 운행 시의 문맥 을 얻 을 수 있 습 니 다. 예 를 들 어:
  • 스 택 호출
  • 현재 스 레 드
  • 시간 소모
  • 매개 변수 와 반환 값
  • 현재 인 스 턴 스 상태
  • 실 현 된 선택 이 절단면 을 실현 하 는 방식 은 다음 과 같은 몇 가지 가 있 습 니 다. 대리 (장식 기) 모델 디자인 모델 에서 장식 기 모델 과 대리 모델 은 해결 하 는 문제 영역 이 다 르 지만 코드 실현 은 매우 비슷 하고 모두 절단면 처 리 를 실현 할 수 있 습 니 다. 여 기 는 등가 로 간주 합 니 다. 여전히 코드 로 설명 합 니 다.
     interface Person {
      void say(String words);
    }
    
    class Officer implements Person {
      public void say(String words) { lie(words); }
      private void lie(String words) {...}
    }
    
    class Proxy implements Person {
      private final Officer officer;
      public Proxy(Officer officer) { this.officer = officer; }
      public void say(String words) {
        enter();
        officer.say(words);
        exit();
      }
      private void enter() { ... }
      private void exit() { ... }
    }
    
    Person p = new Proxy(new Officer());
    상기 enter () 와 exit () 는 절단면 을 실현 하 는 곳 입 니 다.Officer 의 Proxy 인 스 턴 스 를 가 져 오 면 Officer 인 스 턴 스 의 행 위 를 추적 할 수 있 습 니 다. 이런 방식 은 가장 간단 하고 직접적 입 니 다. Java Proxy Java Proxy 는 JDK 에 내 장 된 프 록 시 API 로 반사 체 제 를 통 해 이 루어 집 니 다. 이 를 사용 하면 절단면 을 완성 하 는 것 은 다음 과 같 습 니 다.
     class ProxyInvocationHandler implements InvocationHandler {
      private final Object target;
      public ProxyInvocationHandler(Object target) { this.target = target;}
      public Object handle(Object proxy, Method method, Object[] args) {
        enter();
        method.invoke(target, args);
        exit();
      }
      private void enter() { ... }
      private void exit() { ... }
    }
    ClassLoader loader = ...
    Class<?>[]  interfaces = {Person.class};
    Person p = (Person)Proxy.newInstance(loader, interfaces, new ProxyInvocationHandler(new Officer()));
    이전 방법 과 비교 하면 읽 기 쉽 지 않 지만 더욱 통용 되 지만,구체 적 인 구현 에 대한 의존 도가 매우 적 습 니 다. AspectJ AspectJ 3 는 바이트 코드 를 기반 으로 하 는 AOP 구현 입 니 다. 자바 proxy 에 비해 호출 이 더욱 투명 하고 간단명료 하 며 (DSL 과 유사) 성능 이 좋 습 니 다. 다음 코드:
     pointcut say(): execute(* say(..))
    before(): say() { ... }
    after() : say() { ... }
    Aspectj 가 절단면 을 실현 하 는 시 기 는 두 가지 가 있 습 니 다. 정적 컴 파일 과 클래스 로드 기간 짜 임 (load - time weaving) 입 니 다.또한 IDE 에 대한 지원 이 풍부 합 니 다. CGlib 는 AspectJ 와 마찬가지 로 CGlib 4 도 바이트 코드 를 조작 하여 AOP 를 실현 합 니 다. 사용 상 자바 Proxy 와 매우 비슷 합 니 다. 다만 자바 Proxy 가 인터페이스 에 의존 하지 않 습 니 다. 우리 가 잘 알 고 있 는 Spring, Guice 와 같은 IoC 용기 가 AOP 를 실현 하 는 것 은 모두 이 를 사용 하여 이 루어 집 니 다.
     class Callback implements MethodInterceptor {
      public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
        enter();
        proxy.invokeSuper(obj, args);
        exit();
      }
      private void enter() { ... }
      private void exit() { ... }
    }
    Enhancer e = new Enhancer();
    e.setSuperclass(Officer.class);
    e.setCallback(new Callback());
    Person p = e.create();
    바이트 코드 를 조작 하 는 네 가지 방법 은 각각 적용 되 는 장면 이 있 습 니 다.그러나 실행 중인 자바 프로 세 스 만 동적 추적 을 지원 할 수 없습니다. 물론 제 가 깊이 이해 하지 못 했 을 수도 있 습 니 다. 상기 방안 을 바탕 으로 하 는 방법 이 있 으 면 아낌없이 가르쳐 주 십시오. 아니면 Btrace 5 의 사고 로 돌아 가 자바. lang. Instrumentation 을 통 해 바이트 코드 를 주입 하 는 실현 원 리 를 이해 한 후에동적 변화 추적 방식 이나 목 표를 실현 하 는 데 문제 가 없 을 것 입 니 다. 빌 린 문제, 바이트 코드 를 어떻게 조작 (주입) 하여 절단면 처 리 를 실현 하 는 지 기 쁩 니 다. 기 쁜 것 은 '자신의 모니터링 도 구 를 구축 하 는 것' 7 문 이 저 에 게 좋 은 착안점 을 제공 해 주 었 습 니 다. 이 를 바탕 으로 ASM 8 에 대한 심도 있 는 연 구 를 통 해 실현 할 수 있 습 니 다.
  • 방법 을 호출 하여 들 어 갈 때 현재 인 스 턴 스 (this) 와 매개 변수 값 목록 을 가 져 옵 니 다.
  • 방법 을 호출 할 때 반환 값 을 가 져 옵 니 다.
  • 방법 이 이상 하 게 던 졌 을 때 리 셋 을 실행 하고 이상 한 인 스 턴 스 를 가 져 옵 니 다.
  • 그 절단면 이 실 현 된 핵심 코드 는 다음 과 같다.
      private static class ProbeMethodAdapter extends AdviceAdapter {
    
        protected ProbeMethodAdapter(MethodVisitor mv, int access, String name, String desc, String className) {
          super(mv, access, name, desc);
          start = new Label();
          end = new Label();
          methodName = name;
          this.className = className;
        }
    
        @Override
        public void visitMaxs(int maxStack, int maxLocals) {
          mark(end);
          catchException(start, end, Type.getType(Throwable.class));
          dup();
          push(className);
          push(methodName);
          push(methodDesc);
          loadThis();
          invokeStatic(Probe.TYPE, Probe.EXIT);
          visitInsn(ATHROW);
          super.visitMaxs(maxStack, maxLocals);
        }
    
        @Override
        protected void onMethodEnter() {
          push(className);
          push(methodName);
          push(methodDesc);
          loadThis();
          loadArgArray();
          invokeStatic(Probe.TYPE, Probe.ENTRY);
          mark(start);
        }
    
        @Override
        protected void onMethodExit(int opcode) {
          if (opcode == ATHROW) return; // do nothing, @see visitMax
          prepareResultBy(opcode);
          push(className);
          push(methodName);
          push(methodDesc);
          loadThis();
          invokeStatic(Probe.TYPE, Probe.EXIT);
        }
    
        private void prepareResultBy(int opcode) {
          if (opcode == RETURN) { // void
            push((Type) null);
          } else if (opcode == ARETURN) { // object
            dup();
          } else {
            if (opcode == LRETURN || opcode == DRETURN) { // long or double
              dup2();
            } else {
              dup();
            }
            box(Type.getReturnType(methodDesc));
          }
        }
    
        private final String className;
        private final String methodName;
        private final Label start;
        private final Label end;
    }
    더 많은 참고 사항 은 여기 를 보십시오 Demo , 이것 은 javaagent 입 니 다. 숙주 프로 세 스 가 시 작 된 후에 MBean 은 jconsole 로 동적 추적 관 리 를 할 수 있 습 니 다. 후속 방향 입 니 다.
  • 웹 기반 원 격 인 터 랙 션 인터페이스 제공;
  • Shell 기반 로 컬 명령 행 인 터 페 이 스 를 제공 합 니 다.
  • Profile 통계 와 추세 수출 을 제공한다.
  • 추적 로그 포 지 셔 닝 과 분석 을 제공 합 니 다.
  • 레 퍼 런 스
  • The Java Interactive Profiler
  • Proxy Javadoc
  • Aspectj
  • CGlib
  • BTrace User’s Guide
  • 자바 동적 추적 분석 도구 BTrace 실현 원리
  • 자신의 모니터링 도구 구축
  • ASM Guide
  • 자바 프로 파일 링 도구 에 대한 분석 과 비교 -
  • AOP@Work: Performance monitoring with AspectJ
  • The JavaTM Virtual Machine Specification
  • rednaxelafx 에서 온 JVM 공유, 그의 Blog
  • BCEL
  • 좋은 웹페이지 즐겨찾기