6

log4j ネットワーク アダプタは、イベントをシリアル化された Java オブジェクトとして送信します。このオブジェクトをキャプチャして、別の言語 (python) でデシリアライズできるようにしたいと考えています。これは可能ですか?

ネットワーク キャプチャは簡単です。それは単なるTCPソケットであり、ストリームを読み込んでいます。難点はデシリアライズ部分

4

6 に答える 6

5

一般的に、いいえ。

Java シリアル化のストリーム形式はこのドキュメントで定義されていますが、ストリーム データを元のオブジェクトに近いものに戻すには、元のクラス定義 (およびそれらをロードする Java ランタイム) にアクセスする必要があります。たとえば、クラスは writeObject() および readObject() メソッドを定義して、独自のシリアル化されたフォームをカスタマイズできます。

(編集: lubos hasko は、Python の前でオブジェクトをデシリアライズするための小さな Java プログラムを用意することを提案していますが、問題は、これが機能するためには、「小さな Java プログラム」が、すべての同じクラスの同じバージョンをロードする必要があることです。逆シリアル化. 1 つのアプリからログ メッセージを受信して​​いる場合は注意が必要であり、複数のログ ストリームを多重化している場合は非常に注意が必要です. いずれにせよ、もはや小さなプログラムにはなりませ.ここでは、何がシリアル化されるのかわかりません. log4j クラスだけであれば問題ないはずです. 一方、任意の例外をログに記録することは可能であり、それらがストリームに入れられる場合も同様です.)

log4j ネットワーク アダプターをカスタマイズし、生のシリアル化をより簡単に逆シリアル化された形式に置き換える方がはるかに簡単です (たとえば、XStream を使用してオブジェクトを XML 表現に変換できます)。

于 2008-08-27T04:35:57.700 に答える
2

理論上、可能です。Java のシリアライゼーションは、Javaland のほとんどすべてのものと同様に標準化されています。したがって、Python でその標準に従ってデシリアライザーを実装できます。ただし、Java シリアライゼーション形式は複数の言語で使用できるようには設計されていません。シリアライゼーション形式は、JVM 内でオブジェクトを表現する方法と密接に結びついています。Python で JVM を実装するのは確かに楽しい作業ですが、おそらくあなたが探しているものではないでしょう (-:

言語に依存しないように特別に設計された他の (データ) シリアル化形式があります。それらは通常、データ形式を最小限 (数値、文字列、シーケンス、辞書など) にまで削ぎ落とすことで機能するため、リッチ オブジェクトをダム データ構造のグラフとして表現するには、両端で少し作業が必要になります (その逆も同様です)。逆)。

2 つの例は、JSON (JavaScript Object Notation)YAML (YAML Ain't Markup Language)です。

ASN.1 (Abstract Syntax Notation One)は、別のデータ シリアル化形式です。ASN.1 は、簡単に理解できるようにフォーマットを単純化するのではなく、自己記述的です。つまり、ストリームをデコードするために必要なすべての情報は、ストリーム自体の中でエンコードされます。

もちろん、XML (eXtensible Markup Language)も機能します。ただし、Java オブジェクトの「メモリ ダンプ」のテキスト表現を提供するだけでなく、実際の抽象的で言語に依存しないエンコーディングを提供するために使用される場合に限ります。

つまり、長い話を簡単に言うと、log4j を強制的に上記の形式のいずれかでログに記録させるか、log4j をそれを行うものに置き換えるか、何らかの方法でオブジェクトが送信される前にインターセプトしようとすることです。 Javaland を離れる前に配線して変換します。

JSON、YAML、ASN.1、および XML を実装するライブラリは、Java と Python の両方 (および人類が知っているほとんどすべてのプログラミング言語) で利用できます。

于 2008-08-27T05:05:47.270 に答える
1

理論上は可能です。実際にどれほど難しいかは、Java シリアライゼーション形式が文書化されているかどうかによって異なります。そうではないと思います。編集: おっと、私は間違っていました、チャールズに感謝します。

とにかく、これは私があなたに行うことをお勧めします

  1. log4j からキャプチャし、独自の小さな Java プログラムで Java オブジェクトを逆シリアル化します。

  2. オブジェクトを再び取得したら、独自のカスタム フォーマッタを使用してシリアル化します。

    ヒント:独自のカスタム フォーマッタを作成する必要さえないかもしれません。たとえば、JSON (ライブラリを下にスクロール)には Python と Java のライブラリがあるため、理論的には Java ライブラリを使用してオブジェクトをシリアル化し、Python の同等のライブラリを使用して逆シリアル化することができます。

  3. 出力ストリームを Python アプリケーションに送信し、逆シリアル化します

チャールズは次のように書いています。

問題は、これが機能するためには、「小さな Java プログラム」が、デシリアライズする可能性のあるすべての同じクラスの同じバージョンをロードする必要があることです。1 つのアプリからログ メッセージを受信して​​いる場合は注意が必要ですが、複数のログ ストリームを多重化している場合は非常に注意が必要です。いずれにせよ、もはや小さなプログラムにはなりません。

自分の Java プロセスで単に Java log4j ライブラリを参照することはできませんか? ここでは、任意の言語のペアに適用できる一般的なアドバイスを提供しているだけです (質問の名前は言語にかなり依存しているため、一般的な解決策の 1 つを提供しました)。とにかく、私は log4j に詳しくなく、独自のシリアライザーを「注入」できるかどうかもわかりません。可能であれば、もちろん、あなたの提案ははるかに優れており、クリーンです。

于 2008-08-27T04:41:41.133 に答える
1

XMLなど、両方の言語が理解し、簡単にマーシャリング/アンマーシャリングできるサードパーティ形式に移行することをお勧めします(独自のlog4jアダプタを作成するなど)。

于 2008-08-27T04:45:58.377 に答える
1

私は Python の専門家ではないので、問題の解決方法についてコメントすることはできませんが、.NET にプログラムがある場合は、IKVM.NET を使用して Java オブジェクトを簡単に逆シリアル化できます。Socket アペンダーに書き込まれた Log4J ログ メッセージ用の .NET クライアントを作成して、これを実験しましたが、非常にうまく機能しました。

この回答がここで意味をなさない場合は申し訳ありません。

于 2008-08-27T05:22:24.033 に答える
0

受信側に JVM があり、シリアル化されたデータのクラス定義があり、Python のみを使用し、他の言語を使用したくない場合は、Jython を使用できます。

  • 正しいJavaメソッドを使用して受け取ったものを逆シリアル化します
  • 次に、取得したものを Python コードで処理します
于 2009-02-20T17:34:13.313 に答える