2016-03-18 8 views
3

私はAspectJを使ってjava.net.Socket呼び出しを傍受しています。AspectJはsun.net。*パッケージを織り込むことができますか?

私は、コールスタックは次のようになると、その後、私はコンソール出力を見ることができる非常に単純な側面

after(): call(* java.net.Socket.connect(..)) { 
    System.out.println("Connect intercepted!"); 
} 

とaop.xml

<aspectj> 

    <aspects> 
     <aspect name="com.iggroup.lightstreamer.nwtp.SocketExceptionLoggingAspect"/> 
    </aspects> 

    <weaver options="-Xlint:ignore -Xset:weaveJavaxPackages=true -Xset:weaveJavaPackages=true"> 
    </weaver> 

</aspectj> 

を作成しました:

java.lang.Exception 
    at com.iggroup.lightstreamer.nwtp.SocketExceptionLoggingAspect.ajc$after$com_iggroup_lightstreamer_nwtp_SocketExceptionLoggingAspect$2$6e16217c(SocketExceptionLoggingAspect.aj:39) 
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:337) 
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) 
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) 
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380) 
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) 
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) 
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) 
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) 
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) 
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) 
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55) 
    at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:91) 
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) 
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:596) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557) 
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:475) 
    at com.iggroup.lightstreamer.nwtp.users.SsoRestClientImpl.lambda$0(SsoRestClientImpl.java:68) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 

しかし、コールスタックが次のような場合は、何もログアウトしません。

Caused by: java.net.ConnectException: Connection refused: connect 
       at java.net.DualStackPlainSocketImpl.connect0(Native Method) ~[na:1.8.0_65] 
       at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) ~[na:1.8.0_65] 
       at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_65] 
       at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_65] 
       at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_65] 
       at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[na:1.8.0_65] 
       at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_65] 
       at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_65] 
       at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:668) ~[na:1.8.0_65] 
       at sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:173) ~[na:1.8.0_65] 
       at sun.net.NetworkClient.doConnect(NetworkClient.java:180) ~[na:1.8.0_65] 
       at sun.net.www.http.HttpClient.openServer(HttpClient.java:432) ~[na:1.8.0_65] 
       at sun.net.www.http.HttpClient.openServer(HttpClient.java:527) ~[na:1.8.0_65] 
       at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:781) ~[na:1.8.0_65] 
       at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647) ~[na:1.8.0_65] 
       at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1536) ~[na:1.8.0_65] 
       at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) ~[na:1.8.0_65] 
       at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254) ~[na:1.8.0_65] 
       at com.lightstreamer.ls_client.HttpProvider.connectAndGetAnswer(HttpProvider.java:244) ~[lightstreamer-se-client-2.5.2-1110.jar:na] 

セキュリティマネージャの制限により、sun.net.*パッケージがロードタイムウィービングされていないためです。

sun.net.*パッケージを使用する方法を知っている人はいますか?

アップデート1

私はそれ以上の1(sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStreamls_client.HttpProvider.connectAndGetAnswer呼び出しをインターセプトしますが、できないことを確認します。

sun.*はAspectJで編成できますか?

+0

ロードタイム織りをJavaエージェントで使用していますか? –

+0

@NándorElődFeketeはい、私はウィーバーエージェントでロード時織りを使用しています。 – stackoverflower

+0

FYI、これは私が制御できない 'sun。*'パッケージを使用するサードパーティ製のライブラリです(そして、正気の人は 'sun。*'を使うべきでは全く同意しません)。問題になることはありません、ここstackoverflowの上の私の非常に最初の答えは、[質問]にあった – stackoverflower

答えて

4

私はJRE(ブートストラップ)クラスのロード時に織り成すための成功セットアップをまだ見ていません。これをデバッグのために必要とするならば、JREクラスのビルド時間を代わりに使うことになります。

この短いスニペットは、JRE jarを作成し、weavedクラスを1つの出力jarに入れます。それは依存性としてorg.aspectj/aspectjtoolsを必要とします。また、JREのextサブフォルダのjarファイルはスキップされます。これらのjarファイルには重複したクラスが含まれ、重複ファイルを含むjarファイルを作成するとエラーが発生します。新しいクラスからはjfxswt.jarをスキップします。これは、クラスが見つからないために失敗するためです。

String aspectFileName = "src/main/java/pckg/AspectName.aj"; 
String jreLibPath = "c:/Program Files/Java/jdk1.8.0_40/jre/lib"; 
String outputJar = "weavedjre.jar"; 

List<String> jars = new ArrayList<>(); 

File dir = new File(jreLibPath); 
File[] files = dir.listFiles(); 
for (File file : files) { 
    if (file.isFile() && file.getName().endsWith(".jar") 
      && !file.getName().endsWith("jfxswt.jar")) { 
     jars.add(file.getAbsolutePath()); 
    } 
} 

List<String> ajcArgs = new ArrayList<>(Arrays.asList("-showWeaveInfo")); 
for (String jar : jars) { 
    ajcArgs.add("-inpath"); 
    ajcArgs.add(jar); 
} 
ajcArgs.add(aspectFileName); 
ajcArgs.add("-outjar"); 
ajcArgs.add(outputJar); 

org.aspectj.tools.ajc.Main.main(ajcArgs.toArray(new String[] {})); 

その後(ブートクラスパスの前に追加)編みJREクラスを使用するには、次のVM引数を使用してプログラムを実行します。

-verbose:class -Xbootclasspath/p:${resource_loc:/project_name/weavedjre.jar} 

-verbose:class -Xbootclasspath/p:path_to/weavedjre.jar 

またはEclipse起動構成で

クラスローディングVM引数の冗長なロギングも追加したので、どのクラスがどこからロードされているのか分かります。

+0

私は同じプロブレムを持っています。私はpointcut callUrlOpenConnection()を傍受できません:(実行(public * java.net.URL.openConnection())); –

1

ナンドールが正しくありました。 JREライブラリではLTWを実行できません。なぜなら、ブートクラスパス上にあり、AspectJがそれらを織り込む前にロードされているからです。コンパイル時に織り交ぜてデフォルトのライブラリを置き換えなければならなかった。

ここに私がやったことだ:

ファイルあなたは

workspace 
    |- Aspect.aj 
    |- rt.jar 
    |- aspectjrt-1.8.7.jar 
    |- aspectjtools-1.8.7.jar 

Aspect.aj

package java.net; 

import sun.misc.SharedSecrets; 

import java.io.FileDescriptor; 
import java.lang.reflect.Field; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 

public aspect Aspect { 
    private static Class dualStackPlainSocketImplClass; 
    private static Method localPort0; 

    static { 
     try { 
      dualStackPlainSocketImplClass = Class.forName("java.net.DualStackPlainSocketImpl"); 
      localPort0 = dualStackPlainSocketImplClass.getDeclaredMethod("localPort0", Integer.TYPE); 
      localPort0.setAccessible(true); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
     } 
    } 

    pointcut connect(java.net.DualStackPlainSocketImpl s): target(s) && execution(* java.net.DualStackPlainSocketImpl.socketConnect(..)); 

    after(DualStackPlainSocketImpl s) throwing (Exception e): connect(s) { 
     try { 
      Field fdf = dualStackPlainSocketImplClass.getSuperclass().getSuperclass().getDeclaredField("fd"); 
      fdf.setAccessible(true); 
      FileDescriptor fd = (FileDescriptor) fdf.get(s); 
      int nativeFd = SharedSecrets.getJavaIOFileDescriptorAccess().get(fd); 
      int localPort = (int) localPort0.invoke(dualStackPlainSocketImplClass, nativeFd); 
      System.out.format("[local port=%s][exception=%s]\n", localPort, e.getMessage()); 
     } catch (InvocationTargetException e1) { 
      e1.printStackTrace(); 
     } catch (IllegalAccessException e1) { 
      e1.printStackTrace(); 
     } catch (NoSuchFieldException e1) { 
      e1.printStackTrace(); 
     } catch (NullPointerException e1) { 
      e1.printStackTrace(); 
     } 
    } 
} 

は、アスペクトファイルは、トリッキーなビットを取得する方法で、非常に簡単ですが必要反射を介してローカルポート。

は、いくつかのクラス/メソッドが保護されているためpackage java.net;が重要であることに注意してください。


はその後、ワークスペース

java -cp "aspectjrt-1.8.7.jar;aspectjtools-1.8.7.jar" org.aspectj.tools.ajc.Main -1.8 -inpath rt.jar Aspect.aj -outjar newrt.jar 

から実行すると、あなたはnewrt.jarを取得します。それをあなたのプログラムを実行するに


java -cp <your_class_path> -Xbootclasspath/p:<path_to_newrt.jar> <main_class> 

-Xbootclasspath/pは、ブートクラスパスにnewrt.jarを付加し、JDKのデフォルトを上書きします。

+0

私はあなたが反射トリックを必要としないと思う、ちょうど[特権](https://eclipse.org/aspectj/doc/next/progguide/semantics-aspects.html#aspect-privilege)としてあなたの側面を宣言してください。 –

+0

チップをありがとう。私はそれを試して、この答えを更新します。 – stackoverflower

関連する問題