Frage

Der log4j-Netzwerkadapter sendet Ereignisse als serialisiertes Java-Objekt.Ich möchte dieses Objekt erfassen und in einer anderen Sprache (Python) deserialisieren können.Ist das möglich?

NOTIZ Die Netzwerkerfassung ist einfach;Es ist nur ein TCP-Socket und das Einlesen eines Streams.Die Schwierigkeit liegt im Deserialisierungsteil

War es hilfreich?

Lösung

Im Allgemeinen nein.

Das Stream-Format für die Java-Serialisierung ist definiert in diesem Dokument, aber Sie benötigen Zugriff auf die ursprünglichen Klassendefinitionen (und eine Java-Laufzeitumgebung, in die sie geladen werden können), um die Stream-Daten wieder in etwas umzuwandeln, das den ursprünglichen Objekten nahe kommt.Beispielsweise können Klassen die Methoden writeObject() und readObject() definieren, um ihre eigene serialisierte Form anzupassen.

(bearbeiten: lubos hasko schlägt vor, ein kleines Java-Programm zu haben, um die Objekte vor Python zu deserialisieren, aber das Problem ist, dass Ihr „kleines Java-Programm“, damit dies funktioniert, die gleichen Versionen aller Klassen laden muss, die es deserialisieren könnte.Das ist schwierig, wenn Sie Protokollnachrichten von einer App empfangen, und sehr schwierig, wenn Sie mehr als einen Protokollstream multiplexen.So oder so wird es kein kleines Programm mehr sein. edit2: Ich könnte mich hier irren, ich weiß nicht, was serialisiert wird.Wenn es sich nur um log4j-Klassen handelt, sollte alles in Ordnung sein.Andererseits ist es möglich, beliebige Ausnahmen zu protokollieren, und wenn diese ebenfalls in den Stream eingefügt werden, bleibt mein Standpunkt bestehen.)

Es wäre viel einfacher, den log4j-Netzwerkadapter anzupassen und die Rohserialisierung durch eine einfacher zu deserialisierende Form zu ersetzen (Sie könnten beispielsweise XStream verwenden, um das Objekt in eine XML-Darstellung umzuwandeln).

Andere Tipps

Theoretisch, es ist möglich.Die Java-Serialisierung ist, wie so ziemlich alles in Javaland, standardisiert.Also, du könnte Implementieren Sie einen Deserialisierer gemäß diesem Standard in Python.Das Java-Serialisierungsformat ist jedoch nicht für die sprachübergreifende Verwendung konzipiert, da das Serialisierungsformat eng mit der Art und Weise verknüpft ist, wie Objekte innerhalb der JVM dargestellt werden.Während die Implementierung einer JVM in Python sicherlich eine unterhaltsame Übung ist, ist sie wahrscheinlich nicht das, wonach Sie suchen (-:

Es gibt andere (Daten-)Serialisierungsformate, die speziell für die Sprachunabhängigkeit konzipiert sind.Sie funktionieren normalerweise, indem sie die Datenformate auf das Nötigste reduzieren (Zahl, String, Sequenz, Wörterbuch und das ist alles) und daher auf beiden Seiten ein wenig Arbeit erfordern, um ein umfangreiches Objekt als Diagramm dummer Datenstrukturen (und umgekehrt) darzustellen umgekehrt).

Zwei Beispiele sind JSON (JavaScript Object Notation) Und YAML (YAML ist keine Auszeichnungssprache).

ASN.1 (Abstract Syntax Notation One) ist ein weiteres Datenserialisierungsformat.Anstatt das Format so weit zu reduzieren, dass es leicht verständlich ist, ist ASN.1 selbstbeschreibend, was bedeutet, dass alle zum Dekodieren eines Streams erforderlichen Informationen im Stream selbst kodiert sind.

Und natürlich, XML (eXtensible Markup Language), wird auch funktionieren, vorausgesetzt, dass es nicht nur zur Bereitstellung einer textuellen Darstellung eines „Speicherauszugs“ eines Java-Objekts verwendet wird, sondern eine tatsächliche abstrakte, sprachunabhängige Codierung.

Um es kurz zu machen:Am besten versuchen Sie entweder, log4j zur Protokollierung in einem der oben genannten Formate zu zwingen, log4j durch etwas zu ersetzen, das dies tut, oder zu versuchen, die Objekte irgendwie abzufangen, bevor sie über die Leitung gesendet werden, und sie zu konvertieren, bevor Sie Javaland verlassen.

Bibliotheken, die JSON, YAML, ASN.1 und XML implementieren, sind sowohl für Java als auch für Python (und so ziemlich jede bekannte Programmiersprache) verfügbar.

Ich würde empfehlen, auf ein Drittanbieterformat umzusteigen (indem Sie Ihre eigenen log4j-Adapter usw. erstellen), das beide Sprachen verstehen und problemlos Marshalling/Unmarshaling durchführen können, z. B.XML.

Theoretisch ist es möglich.Wie schwierig es in der Praxis sein könnte, hängt nun davon ab, ob das Java-Serialisierungsformat dokumentiert ist oder nicht.Ich schätze, das ist es nicht. bearbeiten: Hoppla, ich habe mich geirrt, danke Charles.

Wie auch immer, das ist es, was ich Ihnen empfehle

  1. Erfassen Sie von log4j und deserialisieren Sie Java-Objekte in Ihrem eigenen kleinen Java-Programm.

  2. Wenn Sie das Objekt nun wieder haben, serialisieren Sie es mit Ihrem eigenen benutzerdefinierten Formatierer.

    Tipp: Möglicherweise müssen Sie nicht einmal Ihren eigenen benutzerdefinierten Formatierer schreiben.Zum Beispiel, JSON (für Bibliotheken nach unten scrollen) verfügt über Bibliotheken für Python und Java. Sie könnten also theoretisch die Java-Bibliothek zum Serialisieren Ihrer Objekte und die entsprechende Python-Bibliothek zum Deserialisieren verwenden

  3. Senden Sie den Ausgabestream an Ihre Python-Anwendung und deserialisieren Sie ihn

Charles schrieb:

Das Problem ist, dass Ihr "kleines Java -Programm" dieselben Versionen aller Klassen laden muss, die es möglicherweise deserialisieren könnte.Das ist schwierig, wenn Sie Protokollnachrichten von einer App erhalten, und wirklich schwierig, wenn Sie mehr als einen Protokollstrom multiplexen.In jedem Fall wird es kein kleines Programm mehr sein.

Können Sie nicht einfach in Ihrem eigenen Java-Prozess auf Java-Log4j-Bibliotheken verweisen?Ich gebe hier nur allgemeine Ratschläge, die auf jedes Sprachpaar anwendbar sind (der Name der Frage ist ziemlich sprachunabhängig, daher habe ich nur eine der allgemeinen Lösungen bereitgestellt).Jedenfalls kenne ich mich mit log4j nicht aus und weiß nicht, ob man darin einen eigenen Serializer „einschleusen“ kann.Wenn Sie können, ist Ihr Vorschlag natürlich viel besser und sauberer.

Nun, ich bin kein Python-Experte, daher kann ich nicht sagen, wie Sie Ihr Problem lösen können. Wenn Sie jedoch ein Programm in .NET haben, können Sie IKVM.NET verwenden, um Java-Objekte einfach zu deserialisieren.Ich habe damit experimentiert, indem ich .NET-Client für Log4J-Protokollnachrichten erstellt habe, die in den Socket-Appender geschrieben wurden, und es hat wirklich gut funktioniert.

Es tut mir leid, wenn diese Antwort hier keinen Sinn ergibt.

Wenn Sie auf der Empfangsseite über eine JVM und Klassendefinitionen für die serialisierten Daten verfügen können und nur Python und keine andere Sprache verwenden möchten, können Sie Jython verwenden:

  • Sie würden das, was Sie erhalten haben, mit den richtigen Java-Methoden deserialisieren
  • und dann verarbeiten Sie, was Sie mit Ihrem Python-Code erhalten
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top