Connect with us

Künstliche Intelligenz

Core Java: Parallel, aber richtig – Wie Java-Collectors unter Last bestehen


Manchmal reicht es nicht aus, dass Code funktioniert – er muss auch unter Last funktionieren. In modernen Anwendungen, die große Datenmengen verarbeiten, steht Entwicklerinnen und Entwicklern mit der Streams-API in Java ein elegantes, deklaratives Werkzeug zur Verfügung, um Daten in Pipelines zu transformieren, zu filtern und schließlich zu aggregieren. Die Vorstellung, mit wenigen Zeilen komplexe Datenoperationen zu beschreiben, ist nicht nur verführerisch, sondern tatsächlich realistisch. Doch was passiert, wenn diese Operationen auf Millionen von Einträgen treffen? Wenn die Ausführung in mehreren Threads parallel erfolgen soll, um Zeit zu sparen und Mehrkernsysteme effektiv zu nutzen?


Sven Ruppert

Sven Ruppert

Seit 1996 programmiert Sven Java in Industrieprojekten und seit über 15 Jahren weltweit in Branchen wie Automobil, Raumfahrt, Versicherungen, Banken, UN und Weltbank. Seit über 10 Jahren ist er von Amerika bis nach Neuseeland als Speaker auf Konferenzen und Community Events, arbeitete als Developer Advocate für JFrog und Vaadin und schreibt regelmäßig Beiträge für IT-Zeitschriften und Technologieportale.
Neben seinem Hauptthema Core Java beschäftigt er sich mit TDD und Secure Coding Practices.

Genau an dieser Stelle rückt ein Konzept in den Vordergrund, das oft zu wenig Beachtung findet: der Collector. Er ist das Element am Ende einer Stream-Pipeline, das bestimmt, was mit den verarbeiteten Daten geschehen soll. Und obwohl die API einfach erscheint – collect(Collectors.toList()) – verbirgt sich dahinter eine Architektur, die in paralleler Ausführung ganz eigene Herausforderungen mit sich bringt.

Im Folgenden geht es daher nicht nur um die Syntax oder die Mechanik von Collectoren, sondern um ein tiefes Verständnis für die Bedingungen, unter denen sie korrekt und effizient zum Einsatz kommen. Wir schauen auf Standardlösungen des JDK (Java Development Kit), diskutieren individuelle Implementierungen, zeigen typische Fehler – und kommen letztlich zu der Frage: Wie viel Parallelisierung verträgt ein Collector, ohne dass es gefährlich wird?

Die Streams-API von Java vermittelt auf den ersten Blick den Eindruck, dass sich das Sammeln von Ergebnissen – das sogenannte terminale Aggregieren – problemlos parallelisieren lässt. Doch hinter der Methode collect(...) verbirgt sich mehr als nur syntaktische Bequemlichkeit. Sie ist eine koordinierte Zusammenarbeit zwischen einem Datenstrom und einem Collector – einem Objekt, das aus Einzelteilen ein Ganzes formt.

Ein Collector besteht im Kern aus vier funktionalen Komponenten: dem supplier, der für jeden Teilprozess einen neuen Zwischenspeicher bereitstellt; dem accumulator, der Elemente in diesen Zwischenspeicher einspeist; dem combiner, der mehrere Zwischenspeicher zu einem zusammenführt; und schließlich dem finisher, der das Endergebnis produziert. Während supplier und accumulator auch in sequenziellen Streams essenziell sind, tritt der combiner erst dann in Aktion, wenn mehrere Threads unabhängig voneinander gesammelt haben – also bei einem parallelStream().

Hier liegt der erste fundamentale Unterschied zwischen sequenzieller und paralleler Verarbeitung: In einem sequenziellen Stream genügt es, schrittweise in einen einzigen Speicher zu akkumulieren. In der parallelen Variante hingegen entstehen mehrere voneinander isolierte Zwischenspeicher, deren Inhalte später konfliktfrei zu einem Endergebnis verschmolzen werden müssen. Dieses Verschmelzen geschieht durch den combiner – und genau an dieser Stelle entscheidet sich, ob ein Collector für parallele Verarbeitung tauglich ist oder nicht.

Die Tauglichkeit hängt von mehreren Eigenschaften ab: Die Operationen müssen assoziativ sein, also unabhängig von der Kombination der Zwischenergebnisse dasselbe Resultat liefern. Zudem darf kein geteilter Zustand ohne Synchronisierung vorliegen. Und nicht zuletzt müssen die einzelnen Schritte deterministisch und frei von Seiteneffekten bleiben – andernfalls wird aus einer Parallelisierung schnell eine Quelle subtiler Fehler.

Das Wissen um diese strukturellen Anforderungen ist der erste Schritt zu einem bewussten Einsatz paralleler Verarbeitung. Denn nur wer verstanden hat, wie Collector und Stream im Zusammenspiel funktionieren, kann abschätzen, wann ein Performancegewinn möglich ist – und wann man sich stattdessen instabile oder schlicht falsche Ergebnisse einhandelt.

Stellen wir uns vor, ein Stream wird parallel ausgeführt – etwa über ein großes Dataset, das in mehrere Segmente aufgeteilt ist. Jedes dieser Segmente wird nun unabhängig verarbeitet. Was trivial klingt, hat tiefgreifende Implikationen: Sobald mehrere Threads gleichzeitig sammeln, dürfen sich deren Zwischenergebnisse nicht in die Quere kommen. Die Verantwortung für die Korrektheit liegt beim Collector – genauer: bei seiner strukturellen und funktionalen Ausgestaltung.

Die erste grundlegende Eigenschaft ist Assoziativität. Ein combiner-Aufruf muss unabhängig von der Reihenfolge konsistente Ergebnisse liefern. combine(a, b) und combine(b, a) müssen äquivalente Resultate erzeugen. Das ist notwendig, weil die Reihenfolge der Kombination in einem parallelen Kontext vom Scheduler abhängt – und somit unvorhersagbar ist.

Der zweite Punkt betrifft den Zugriff auf Speicherstrukturen. Sobald ein Collector während der Akkumulation einen gemeinsamen, veränderbaren Zustand nutzt – etwa eine nicht synchronisierte Liste oder Map – entsteht ein potenzieller Hotspot für Race Conditions. Der Collector muss entweder ausschließlich mit lokalen, thread-isolierten Zwischenspeichern arbeiten oder sich auf nebenläufige Datenstrukturen stützen, wie etwa ConcurrentHashMap, LongAdder oder explizit synchronisierte Wrapper.

Darüber hinaus ist auch Determinismus ein wesentliches Kriterium: Eine parallele Ausführung darf nicht zu unterschiedlichen Ergebnissen führen – weder inhaltlich noch strukturell. Insbesondere bei ungeordneten Strukturen wie HashSet oder HashMap ist Vorsicht geboten, da die Iterationsreihenfolge variieren kann – was bei Collectors.joining() oder Collectors.toMap() problematisch wird, wenn die Anwendung auf Ordnung angewiesen ist.

Die drei Anforderungen Assoziativität, isolierter Zustand und Determinismus bilden den technischen Prüfstein für parallele Collectoren. Sie sind nicht optional, sondern grundlegend. Wer sie ignoriert, riskiert schwer zu reproduzierende Fehler, unvollständige Ergebnisse oder performante, aber semantisch falsche Ausgaben.

Beispiele aus der Java-Standardbibliothek: Ein naheliegender Weg, um das abstrakte Konzept paralleler Collectoren greifbar zu machen, führt über die bereits in der Java-Standardbibliothek enthaltenen Collectors. Viele Entwickler nutzen Collectors.toList(), toSet() oder joining() nahezu täglich – selten jedoch im Wissen darum, ob und wie sich diese Collectoren in einem parallelen Kontext verhalten.

Ein einfaches Beispiel: Der Collector Collectors.toList() nutzt intern eine ArrayList. Diese ist nicht thread-sicher. Folglich ist das Ergebnis bei paralleler Verwendung potenziell inkonsistent, sofern nicht intern für Isolation der Zwischenspeicher gesorgt ist.


public static 
Collector> toList() {
   return new CollectorImpl<>(ArrayList::new, List::add,
                              (left, right) -> { left.addAll(right); return left; },
                              CH_ID);
}


Tatsächlich funktioniert dieser Collector in parallelen Streams dennoch korrekt, weil die Streams-API jedem Thread seinen eigenen Akkumulationsbereich zuteilt und erst am Ende über einen kombinierten Merge-Prozess zusammenführt. Der entscheidende Punkt liegt also nicht in der Datenstruktur selbst, sondern in ihrer kontrollierten Isolierung.

Weniger robust zeigt sich Collectors.groupingBy(...). Diese Variante basiert auf einer HashMap, die nicht für gleichzeitigen Zugriff ausgelegt ist. Wird dieser Collector ohne Schutzmaßnahmen in einem parallelStream() eingesetzt, drohen Race Conditions. Die Standardlösung dafür lautet Collectors.groupingByConcurrent(...), die intern auf ConcurrentHashMap setzt und somit für gleichzeitigen Zugriff konzipiert ist.


public static 
Collector>>
groupingByConcurrent(Function super T, ? extends K> classifier) {
   return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
}


Ein Blick auf die Signatur dieser Methode zeigt bereits die Intention:


Map> result = namen.parallelStream()
    .collect(Collectors.groupingByConcurrent(String::length));


In diesem Beispiel werden Strings nach ihrer Länge gruppiert – in einer parallel verarbeitbaren Weise. Entscheidend ist, dass sowohl die Map-Implementierung als auch der Akkumulationsprozess thread-safe sind.

Ebenso interessant ist Collectors.toConcurrentMap(...), der explizit dafür vorgesehen ist, große Mengen von Key-Value-Paaren parallel zu aggregieren. Hier ist die Kombination von Schlüsselkonflikten und der richtige Umgang mit Merge-Funktionen von besonderem Interesse.

Die Erkenntnis aus diesen Beispielen lautet: Nicht jeder Standard-Collector ist per se für Parallelität geeignet. Nur weil eine Methode aus dem Collectors-Baukasten stammt, bedeutet das nicht, dass sie in jeder Ausführungskonfiguration korrekt funktioniert. Der Kontext entscheidet – und mit ihm die verwendete Datenstruktur, das Verhalten des combiner und die Art der Akkumulation.

Wer also aus einem Stream nicht nur ein beliebiges Ergebnis, sondern ein korrektes und performantes Ergebnis ziehen will, sollte die Wahl seines Collectors ebenso sorgfältig treffen wie das Filterkriterium am Anfang der Pipeline.

So mächtig die vorgefertigten Collectors der Java-Standardbibliothek auch sein mögen, manchmal reichen sie für spezifische Anforderungen nicht aus. Besonders wenn domänenspezifische Aggregationen, spezialisierte Datenstrukturen oder nicht-triviale Reduktionslogik benötigt werden, lohnt sich ein Blick auf die Möglichkeit, eigene Collector-Implementierungen zu erstellen.

In der Regel lässt sich ein eigener Collector mit der statischen Methode Collector.of(...) erstellen. Diese Methode erwartet fünf Parameter: einen Supplier, der einen neuen Akkumulator erzeugt; einen BiConsumer, der ein Element in den Akkumulator einfügt; einen BinaryOperator zum Kombinieren zweier Akkumulatoren; optional eine Function zur Konvertierung des Ergebnisses; und schließlich ein Array Collector.Characteristics..., das Metainformationen wie CONCURRENT oder UNORDERED bereitstellt.

Ein einfacher, aber aussagekräftiger Collector könnte etwa Zeichenketten parallel zu einer ConcurrentLinkedQueue sammeln:


Collector> toConcurrentQueue() {
    return Collector.of(
        ConcurrentLinkedQueue::new,
        Queue::add,
        (left, right) -> { left.addAll(right); return left; },
        Collector.Characteristics.CONCURRENT, Collector.Characteristics.UNORDERED
    );
}


Dieser Collector ist sowohl CONCURRENT als auch UNORDERED, das bedeutet: Er kann von mehreren Threads gleichzeitig beschrieben werden, ohne dass die Einfügereihenfolge garantiert werden muss. Wichtig ist dabei, dass ConcurrentLinkedQueue als thread-sichere Datenstruktur fungiert und die Operation addAll ebenfalls nebenläufig unkritisch ist.

Doch auch komplexere Szenarien sind denkbar, etwa das parallele Ermitteln von statistischen Kennzahlen (Minimum, Maximum, Durchschnitt) über eine Datenmenge. In solchen Fällen kann ein record als Akkumulatorstruktur dienen, der in sich bereits alle benötigten Teilzustände kapselt. Der combiner muss dann lediglich diese Strukturen feldweise konsolidieren.

Eigene Collector-Implementierungen zwingen dazu, sich mit der Parallelisierbarkeit der genutzten Datenstrukturen und der Kombinierbarkeit der Aggregationslogik intensiv auseinanderzusetzen. Das ist kein Nachteil, sondern ein wertvoller Lerneffekt. Denn nur wer versteht, was ein Collector im Inneren macht, kann ihn bewusst und sicher einsetzen.

Wer Collectoren im Parallelisierungskontext produktiv einsetzen möchte, sollte einige bewährte Strategien berücksichtigen – nicht als starre Regeln, sondern als Orientierungsrahmen für robuste und effiziente Implementierungen.

Ein erster Grundsatz lautet: Nur parallelisieren, wenn ein echter Nutzen zu erwarten ist. Kleine Datenmengen, triviale Transformationen oder IO-gebundene Prozesse profitieren in der Regel nicht von parallelStream(). Im Gegenteil: Der Overhead des Thread-Managements kann den potenziellen Performancegewinn sogar übersteigen. Eine Parallelisierung lohnt sich erst dann, wenn die zu verarbeitenden Datenmengen hinreichend groß und die Operationen CPU-intensiv sind.

Zweitens: Nur thread-sichere oder isolierte Datenstrukturen verwenden. Das bedeutet entweder, dass jeder Thread seinen eigenen Akkumulator nutzt – was die Streams-API intern unterstützt – oder dass explizit nebenläufige Datenstrukturen wie ConcurrentHashMap, ConcurrentLinkedQueue oder atomare Wrapper eingesetzt werden.

Drittens: Collectors gezielt auswählen. Die Standardbibliothek bietet mit groupingByConcurrent, toConcurrentMap oder mapping leistungsfähige Werkzeuge, die speziell für den parallelen Einsatz konzipiert wurden. Wer darüber hinaus eigene Lösungen entwickelt, sollte besonderes Augenmerk auf den combiner und die Assoziativität der Logik legen.

Viertens: Ergebnisse validieren – insbesondere bei neuen oder komplexen Pipelines. Parallele Streams verhalten sich nicht deterministisch in der Ausführung, deshalb sind Tests in unterschiedlichen Auslastungsszenarien und unter variierender Last notwendig. Das gilt vor allem dann, wenn Entwicklerinnen oder Entwickler Collectoren selbst entwickeln oder anpassen.

Und nicht zuletzt: Messen statt vermuten. Tools wie JMH (Java Microbenchmark Harness), Flight Recorder oder async-profiler helfen dabei, realistische Aussagen über die Performancevorteile zu treffen. Parallelisierung ohne Metriken ist wie Blindflug mit Rückenwind – vielleicht schneller, aber womöglich in die falsche Richtung.



Source link

Weiterlesen
Kommentar schreiben

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Künstliche Intelligenz

Klein, aber günstig: Plant Apple ein Billig-MacBook?


Kommt im Oktober oder November ein billiges MacBook? Die Gerüchteküche glaubt daran und behauptet, dass Apple eine Renaissance des 12-Zoll-Geräts aus Intel-Zeiten plant – nur diesmal mit kostengünstigem, aber dennoch schnellem Apple-Silicon-Prozessor. Es soll sich angeblich um ein auf 13 Zoll leicht vergrößertes Einsteigermodell handeln, das womöglich zusammen mit einem iPad Pro M5 erscheint.

Abseits des Billigmodells soll die zweite Jahreshälfte im Hinblick auf Macs eher uninteressant werden: Laut Angaben des üblicherweise gut informierten Bloomberg-Journalisten Mark Gurman hat Apple seine ersten M5-Macs ins kommende Jahr verschoben. Das betrifft insbesondere die MacBook-Pro-Modelle, die zuletzt im Herbst 2024 überholt worden waren. Als denkbar galten aber auch ein Mac mini M5 oder ein iMac M5, während ein MacBook Air mit dem neuen SoC nicht vor Mai 2026 zu erwarten ist. Doch nun scheint es wohl nur einen einzigen neuen Mac bis Ende 2025 zu geben.

Um den Preis niedrig zu halten, hat Apple der Gerüchteküche zufolge vor, zum zweiten Mal überhaupt einen iPhone-Chip in einen Mac einzubauen. Der im Backend-Code von Apple Intelligence als „Mac17,1“ bezeichnete Rechner kommt offenbar mit dem A18-Prozessor aus dem iPhone 16, das im September 2024 erstmals auf den Markt kam. Ob es sich um die Pro-Version aus den Pro- und Pro-Max-Modellen handelt, ist noch unklar. Diese kommt mit insgesamt he sechs CPU- und GPU-Kernen – möglicherweise reduziert Apple für das neue MacBook deren Anzahl (sogenanntes Binning). Es ist weiterhin damit zu rechnen, dass Apple mindestens 16 GByte RAM verbaut. (Apples erster iPhone-Chip in einem Mac war im Mac mini für Entwickler, kurz nachdem Apple Silicon angekündigt worden war.)

Der A18 Pro ist ausreichend schnell: Er schlägt Apples M1, der bei Erscheinen vor fünf Jahren vielfach gelobt wurde, im Geekbench-Mehrkern-Benchmark um immerhin knapp 800 Punkte. Im Einkern-Benchmark sind es sogar über 1000 Punkte mehr. Das sollte für gängige Standardanwendungen auf einem MacBook genügen. Das gilt insbesondere, wenn man sich an das alte 12-Zoll-MacBook erinnert. Die lüfterlosen Core-M-Chips von Intel (später auch abgespeckte i5- und i7-Prozessoren) kamen schnell ins Schwitzen.

Vom Preis her könnte Apple bei unter 1000 US-Dollar landen, selbst 800 oder 900 Dollar wären drin (Euro-Preise wie üblich darüber), wenn der Konzern das möchte. Die Hardware muss sich vom MacBook Air unterscheiden, das ebenfalls vergleichsweise kompakt ist und auch als 13-Zoll-Modell verkauft wird.

Das heißt: Das neue MacBook müsste wohl flacher und insgesamt kompakter sein. Beim 12-Zoll-MacBook hatte Apple auf die besonders dünne, aber auch unzuverlässige Butterfly-Tastatur gesetzt. Das dürfte der Konzern nicht wiederholen. Allerdings könnte er sich an der Bauweise orientieren, bei der die Tastatur nahezu randlos im Gehäuse steckte. Der verbaute LC-Bildschirm dürfte ein Standard-Screen von der Stange sein. Mit einem matten Nanotextur-Display ist eher nicht zu rechnen.


(bsc)



Source link

Weiterlesen

Künstliche Intelligenz

Heimische Produktion: Apple kauft für eine Halbe Milliarde US-Magnete


Im Konflikt mit der Trump-Regierung um eine mögliche iPhone-Produktion in den USA will Apple offenbar nicht nachgeben – zu teuer und aufwendig scheint dies für den Lieferketten-optimierten Konzern zu sein. Intern glaubt Apple augenscheinlich nicht, dass die Verlagerung der Produktion aus China oder Indien eine realistische Option ist. Trotzdem will das Unternehmen stärker in den USA investieren. Am Dienstag kündigte Apple einen großangelegten Deal über Komponenten an. Es geht, so Apple in einer Mitteilung, um Neodym-Magnete im Wert von einer halben Milliarde US-Dollar.

Apple will demnach zusammen mit dem Spezialanbieter MP Materials eine neuartige Recycling-Fabrik aufbauen, die Magnetmaterialien aus seltenen Erden aus Geräten und Komponenten zurückgewinnt und daraus dann fertige Magnete herstellt. Diese kommen in diversen Apple-Produkten vor – vom MacBook über das iPhone bis zu MagSafe-Zubehör.

MP Materials ist laut Apples Angaben der einzige vollständig integrierte Hersteller seltener Erden in den Vereinigten Staaten. Die Produktionsanlage steht in Fort Worth, Texas, eine weitere Recyclingfabrik soll in Mountain Pass, Kalifornien entstehen. Apple will mit MP Materials außerdem neuartige Magnetmaterialien entwickeln sowie „innovative Verarbeitungstechnologien, um die magnetische Leistung zu steigern“.

Die 500 Millionen Dollar sollen laut Mitteilung „über mehrere Jahre“ ausgegeben werden. Ob es sich um Kaufverträge oder auch Produktionszuschüsse handelt, blieb zunächst unklar. In China bezahlt Apple Fertigern teilweise ihre Maschinen beziehungsweise finanziert diese vor.

Apple nutzt seit längerem „fast“ nur noch Magneten aus Recyclingmaterial, um den Kauf von teurer Neuware zu vermeiden – zudem tut man dies laut eigenen Angaben aus Umweltschutzgründen. Erstmals hatte Apple im Jahr 2019 in der Taptic-Engine (Vibrationsmotor) des iPhone 11 Recycling-Magnete verbaut, die Nutzung seither gesteigert. MP Materials soll mit seinen Magneten die gesamte Apple-Lieferkette versorgen, also auch die Fertiger in China oder Indien. Das dürfte der US-Regierung gefallen. Apple will laut eigenen Angaben in den kommenden vier Jahren bis zu 500 Milliarden Dollar in den USA investieren.


(bsc)



Source link

Weiterlesen

Künstliche Intelligenz

Bundesverfassungsgericht zu Ramstein: Schutzanspruch ist keine Schutzpflicht


Das Bundesverfassungsgericht bekräftigt in einem Urteil zur Airbase Ramstein die universelle Bindungswirkung der Grundrechte, verweigert zugleich aber drei Jemeniten die Durchsetzung ihres Schutzanspruchs. Das Kernargument: Weil die USA im Drohnenkrieg nicht systematisch gegen Grund- und Menschenrechte verstießen, folge aus dem grundrechtlichen Schutzanspruch der Kläger keine Pflicht für die Bundesrepublik, einzugreifen. Weitere Argumente sind die Bündnisfähigkeit Deutschlands und ein Vorrang für vertretbare Einschätzungen durch „zuständige deutsche Staatsorgane“. Fast 5 Jahre nachdem das Bundesverwaltungsgericht die Klage von Faisal bin Ali Jaber, Ahmed Saeed bin Ali Jaber und Khaled Mohmed bin Ali Jaber abgeschmettert hat, scheitern sie also auch beim Bundesverfassungsgericht (BVerfG).

Bei einem Flugdrohnenangriff im Sommer 2012 sind zwei Familienmitglieder der Beschwerdführer im Dorf Khashamer getötet worden. Die Drohne soll über den US-Luftwaffenstützpunkt im deutschen Ramstein aus ferngesteuert worden sein. Die Überlebenden leiden nach eigenen Angaben bis heute unter Folgen. Sie werfen der Bundesrepublik Deutschland vor, ihrer Verpflichtung zum Schutz des Grundrechts auf Leben und Unversehrtheit nicht nachgekommen zu sein.

Der 2. Senat des BVerfG stellt laut Pressemitteilung in seiner Entscheidung vom Dienstag (Az. 2 BvR 508/21) fest, dass „der Bundesrepublik Deutschland ein allgemeiner Schutzauftrag dahingehend, dass der Schutz grundlegender Menschenrechte und der Kernnormen des humanitären Völkerrechts auch bei Sachverhalten mit Auslandsberührung gewahrt bleibt“, obliege. Doch nur unter besonderen Bedingungen folge daraus die Pflicht, etwas zu unternehmen: „Dieser Schutzauftrag kann sich unter bestimmten Bedingungen je nach Einzelfall zu einer konkreten grundrechtlichen Schutzpflicht verdichten“, heißt es in den Leitsätzen der Entscheidung. „Eine solche Schutzpflicht aus Art. 2 Abs. 2 Satz 1 GG bezieht sich auf die Einhaltung des anwendbaren Völkerrechts zum Schutz des Lebens. Sie erfasst auch Gefährdungen, die von einem anderen Staat ausgehen.“

Eine Einschränkung auf den Schutz von Einwohnern oder Staatsbürgern Deutschlands lehnt das BVerfG ausdrücklich ab. Damit gehe das Gericht über seine bisherige Rechtsprechung hinaus, betonte die Vorsitzende Richterin. Gehe es um Handeln von Drittstaaten im Ausland, liegt die Latte laut dem Urteil allerdings hoch: Dem Schutz des Lebens dienende Regeln des humanitären Völkerrechts und der internationalen Menschenrechte müssten „systematisch verletzt“ werden. Und das hätten die Beschwerdeführer nicht bewiesen. Zudem sei die Bündnisfähigkeit der Bundesrepublik ein Verfassungsgut, das zu berücksichtigen sei.

„Die (hohe) Zahl ziviler Opfer kann für sich genommen – ohne Hinzutreten weiterer Elemente – die ernsthafte Gefahr systematischer Verstöße gegen das hier einschlägige Völkerrecht nicht begründen“, erkennt das BVerfG. „Hinreichende Anhaltspunkte dafür, dass im Jemen systematisch gegen das Verbot exzessiver Kollateralschäden verstoßen worden ist, sind den angeführten Berichten und Resolutionen nicht zu entnehmen.“ Die New America Foundation geht aktuell von bis zu 1800 Opfern des Drohnenkriegs im Jemen aus, davon bis zu 150 Zivilisten.

Zwar mögen USA und BRD „im Einzelnen“ unterschiedlicher Auffassung über Völkerrecht sein. „Dadurch wird das grundsätzlich zwischen Bündnispartnern herrschende Vertrauen in die Rechtmäßigkeit des Handelns des anderen aber jedenfalls so lange nicht infrage gestellt, wie sich die von der Bundesrepublik Deutschland abweichende Rechtsauffassung der USA im Rahmen des völkerrechtlich Vertretbaren hält“, erwägt der Senat. „Dies ist hier der Fall.“

Zu entscheiden haben das offenbar deutsche Bundesminister; denn laut Verfassungsurteil ist „die Rechtsauffassung der für außen- und sicherheitspolitischen Fragen zuständigen deutschen Staatsorgane, denen das Grundgesetz für die Regelung der auswärtigen Beziehungen einen grundsätzlich weit bemessenen Spielraum einräumt, maßgeblich zu berücksichtigen, soweit sich diese als vertretbar erweist.“ Deutsche Gerichte können in diesem Bereich also falsche Auslegungen seitens der Regierung nicht für unanwendbar erklären, nur weil sie falsch sind, sondern erst, wenn sie unvertretbar sind.

Ahmed und Khaled bin Ali Jaber nennen das heutige Urteil „gefährlich und erschütternd: Es vermittelt die Botschaft, dass Staaten, die das US-Drohnenprogramm unterstützen, keine Verantwortung tragen, wenn Zivilisten dabei getötet werden.“ Sie hätten nicht nur für sich und ihre ermordeten Angehörigen geklagt, sondern für unschuldige Opfer weltweit, schreiben sie in einer vom European Center for Constitutional and Human Rights (ECCHR) veröffentlichten Pressemitteilung. „An wen sollen wir uns jetzt noch wenden, wenn wir Gerechtigkeit suchen?“

Einen positiven Aspekt sieht Andreas Schüller vom ECCHR: Die Entscheidung lasse „die Tür offen für zukünftige Fälle. Verletzungen des Völkerrechts können gerichtlich überprüft werden, auch wenn das Gericht dafür hohe Hürden aufstellt. Dies ist eine wichtige Feststellung des Bundesverfassungsgerichts in diesen Zeiten.“


(ds)



Source link

Weiterlesen

Beliebt