2009-08-11 6 views
4

컴파일 된 클래스 파일을 구문 분석하는 동안 메소드 본문의 다른 클래스에 대한 호출로 주어진 클래스의 호출을 바꾸길 원합니다 ...
또는 다른 방법으로 넣으면 사용법을 감지하는 방법이 있습니까? 메서드에서 해당 클래스의 일부만을 javaassist과 같은 것을 사용하여 바꿉니다. 제가컴파일 된 Java 클래스 내에서 메소드 호출 재 작성

class A { public int m() { int i = 2; B.multiply(i,i); return i; } } 

의 컴파일 된 버전이 있다면

class A { public int m() { int i = 2; C.divide(i,i); return i; } } 

내가 대안 알고 수행하는 코드를 B의 이용을 검출하고 변경하는 방법은, 예를 들면

.. 존재 파서를 사용하여 소스 파일을 grep하는 것이지만 새로 컴파일 된 클래스 파일을 생성하기 위해 리플렉션을 사용하는 것과 같은보다 우아한 솔루션을 선호합니다.

의견이 있으십니까?

+0

면책 조항 : 저는 java 코더가 아닙니다. IE의 질문에 대답하는 함수를 재정의하지 않는 이유는 무엇입니까? 클래스 A2는 {public int m() {int i = 2; C.divide (i, i); i를 되 돌린다. }} –

+0

[AspectJ] (http://www.eclipse.org/aspectj/)와 같은 AOP 프레임 워크는 원하는 것을 할 수 있어야한다. – gustafc

답변

1

컴파일 된 Java 용 바이트 코드 형식이 지정되며이를 조작하는 제품이 있습니다.

library에는 필요한 기능이있는 것으로 보입니다. 이러한 변형을 안정적으로 수행하는 것이 얼마나 쉬운 지 전혀 모르겠습니다.

0

응용 프로그램을 시작하기 전에 디스크의 실행 파일이 수정되는 이러한 작업을 미리 수행하는 것이 훨씬 쉽습니다. 런타임에 메모리에서 코드를 조작하는 것은 C/C++에서 메모리의 코드를 조작하는 것보다 훨씬 오류가 발생하기 쉽습니다. 왜 이럴 필요가 있니?

3

이 @djna 당신이 그들을로드하기 전에 바이트 코드 파일을 수정하는 것이 가능하다 말했듯이,하지만 당신은 아마 이렇게하지 않으 :

  • 코드 수정을 수행하는 코드는 복잡 할 것입니다 유지하기가 어렵다.
  • 수정 된 코드는 디버그하기가 어려울 수 있습니다. 시작 단계에서 소스 레벨 디버거는 실제로 편집중인 코드에 더 이상 해당하지 않는 소스 코드를 보여줍니다.

바이트 코드 재 작성은 경우에 따라 유용합니다. 예를 들어 JDO 구현은 바이트 코드 재 작성을 사용하여 객체 멤버 페치를 지속성 라이브러리에 대한 호출로 대체합니다. 그러나 이러한 파일의 소스 코드에 액세스 할 수 있으면 소스 코드를 사전 처리 (또는 생성)하여 더 나은 (즉 유지 관리가 용이 ​​한) 솔루션을 얻을 수 있습니다.

EDIT : AOP 또는 Groovy는 예상 할 수있는 재 작성 정도에 따라 실용적인 대안을 선호합니다.

+0

유권자들 - 이유를 언급하기 위해 신경 써야합니까? –

1

Groovy 사용에 신경 쓸 필요가 없다면 B.multiply에 대한 호출을 가로 채고 C.divide으로 바꿀 수 있습니다. 예 here을 찾을 수 있습니다.

2

BCEL 또는 ASM.

최근 Java 클래스 파일을 읽는 데 필요한 여러 라이브러리를 살펴 보았습니다. BCEL은 가장 빠르며, 의존성이 가장 적고, 상자 밖으로 컴파일되었고, 맛있게 간단한 API를 가졌습니다. ASM이 더 많은 의존성을 가지기 때문에 BCEL을 ASM으로 선호했습니다 (API는 평판이 좋지만 단순합니다).

앞서 언급 한 AspectJ는 또 다른 실행 가능한 옵션이다.

BCEL은 정말 간단합니다. 당신은 코드의 세 줄에 방법의 목록을 얻을 수 있습니다 :

ClassParser cp = new ClassParser("A.class"); 
JavaClass jc = cp.parse(); 
Method[] m = jc.getMethods(); 

는 방법의 지침을 얻을 수있는 방법, 나는 생각을 포함하여 더 성찰 다른 API 시설이 있습니다. 그러나이 솔루션은 AspectJ보다 어려울 것이다.

다른 방법은 연산을 호출하는 코드의 모든 인스턴스를 변경하는 대신에 곱셈 또는 나누기 메서드 자체를 변경하는 것입니다. BCEL (또는 ASM)을 사용하는 것이 더 쉬운 길입니다.