2013-08-09 8 views
6

W idealnej sytuacji odpowiedź będzie niezależna od platformy, ale przydatne będą również specyficzne dla platformy, w szczególności Oracle JVM. Projekt, nad którym pracuję, nadal działa w wersji 6 JVM.Jak programowo zarejestrować długość kolejki zdarzeń AWT/Swing?

Szczególna potrzeba ma związek z interfejsem graficznym, który jest "zamrażany" od czasu do czasu. Doskonale zdaję sobie sprawę z pracy GUI nad EDT. Program działał dobrze w systemie Windows, ale po przejściu na Linuksa zaczęły się dziać te "dziwne" problemy z GUI. W rzeczywistości problem ten wystąpił w dwóch aplikacjach, zarówno po przeniesieniu systemu Windows do systemu Linux. JVisualVM pokazuje ponad 10 milionów obiektów java.awt.EventQueueItem. Podejrzewa się, że kolejka AWT rośnie szybciej niż w Linuksie, więc chodzi o to, aby umieścić wskaźnik długości kolejki AWT na aplikacji i zobaczyć, co pokazuje, gdy kolejka rośnie/maleje.

Trochę Googling znalazł this, ale wykonuje liniowy skan kolejki. Może jest jakiś lepszy sposób?

+1

Aby zbadać, można przechwytywać zdarzenia, jak pokazano [tutaj] (http://stackoverflow.com/q/3158254/230513). – trashgod

+0

Dziesięć _million_! 'setCoalesce (false)'? – trashgod

+0

Nie. Już o tym pomyślałem i to zeskanowałem. Nie wyłączając logiki koalescencyjnej. –

Odpowiedz

3

Interesujący temat. Mam zbadać kod EventQueue trochę, a ja nie rozwiązały problemu, mogę mieć kilka przydatnych wskazówek:

  1. wdrożenie Oracle EventQueue nie prowadź zmiennej wielkości, więc jeśli nie przejmie pełną kontrolę nad EventQueue (patrz 3), nie ma możliwości, aby zrobić lepsze niż liniowy skan kolejki podczas korzystania z JRE Oracle.
  2. Możesz napisać, że jesteś własną EventQueue (prawdopodobnie wklejasz i wklejasz implementację Oracle plus kilka poprawek ** będzie najłatwiejsza) i użyjesz EventQueue.push(EventQueue) do zainstalowania własnej implementacji. Wszystkie zdarzenia w kolejce zostaną przeniesione do kolejki, aby można było je liczyć, gdy są one wysyłane do kolejki. Niestety, wciąż jest to skan liniowy, ale przynajmniej teraz jest niezależny od platformy.
  3. Alternatywnie, możesz zainstalować własną implementację EventQueue (patrz 2) tak szybko, jak to możliwe po utworzeniu oryginalnej kolejki zdarzeń (zrób to w statycznym bloku kodu na początku klasy zawierającej twoją główną metodę). Wtedy twoja implementacja może liczyć wszystkie zdarzenia w momencie ich publikacji i nie musisz skanować kolejki, kiedy chcesz poznać jej rozmiar. Musisz po prostu mieć nadzieję, że nikt inny nie popchnie własnego EventQueue na swoim;)

** Niektóre poprawki: Nie próbowałem tego, ale chciałbym usunąć cały publiczny/chroniony kod statyczny (wszyscy odwołując się do tych metod/zmiennych, w jakikolwiek sposób używa java.awt.EventQueue, a więc możesz), dodaj zmienną rozmiaru i zaktualizuj tę zmienną w następujących czterech metodach: postEvent(AWTEvent, int), getNextEventPrivate(), getNextEvent(int) i removeSourceEvent(Object, boolean).

Duży problem z tą modyfikacją, jest fakt, że EventQueue sprawia, że ​​niektóre połączenia do metod AWT z domyślnymi widoczności (na przykład, Toolkit.getEventQueue() i Component.getAccessControlContext()), które nie są dozwolone zadzwonić ponieważ implementacja będzie w innym opakowaniu . Będziesz musiał znaleźć obejście dla każdej sprawy indywidualnie.

+0

"Kopiuj-wklejanie" co to jest ?, może rozszerzyć 'EventQueu', a następnie' wypchnąć' jego własną implementację .. – nachokk

+0

Problem polega na tym, że musisz zmodyfikować prywatne metody, co oznacza ponowne ich wdrożenie. Ponieważ cały kod z java.awt.EventQueue wywołuje ich "własne" metody prywatne, konieczne jest również ponowne wdrożenie tych metod. Ten łańcuch ponownego wdrażania zatrzymuje się dopiero po osiągnięciu publicznych lub chronionych metod. Ponadto, jeśli łańcuch zawiera metody z domyślną widocznością, które są wywoływane z innego miejsca w java.nie można przekierować wszystkich wywołań do prywatnych metod do własnych implementacji. Ze względów praktycznych lepiej jest skopiować i wkleić. –