2016-08-19 7 views
0

При выполнении программирования на низком уровне X11 обычно необходимо вызвать XFree() для возвращаемых структур. Например XGetWMName, я сделал это в следующем коде, который затем взрывается через несколько секундJNA X11 и XFree

AssertionMessage: *** Error in `/opt/jdk1.8.0_40/bin/java': double free or corruption (fasttop): 0x00007f7ca822bdd0 *** 

Это вызвано вызовом XFree(), если удаляется проблема исчезает. Однако мониторинг процесса с верхней показывает устойчивый рост памяти предлагая мне сделать это нужно ...

public class X11WindowFinder { 

    private X11 x11; 

    public X11WindowFinder() { 
     x11 = X11.INSTANCE; 
    } 

    public List<Window> find(Pattern title) { 
     Display display = x11.XOpenDisplay(null); 
     Window root = x11.XDefaultRootWindow(display); 
     List<Window> windows = recurse(x11, display, root, title); 
     x11.XCloseDisplay(display); 
     return windows; 
    } 

    private synchronized List<Window> recurse(X11 x11, Display display, Window root, Pattern pattern) { 
     List<Window> windows = new ArrayList<>(1); 
     X11.WindowByReference windowRef = new X11.WindowByReference(); 
     X11.WindowByReference parentRef = new X11.WindowByReference(); 
     PointerByReference childrenRef = new PointerByReference(); 
     IntByReference childCountRef = new IntByReference(); 

     x11.XQueryTree(display, root, windowRef, parentRef, childrenRef, childCountRef); 
     if (childrenRef.getValue() == null) { 
      return Collections.emptyList(); 
     } 

     long[] ids = {}; 

     if (Native.LONG_SIZE == Long.BYTES) { 
      ids = childrenRef.getValue().getLongArray(0, childCountRef.getValue()); 
     } else if (Native.LONG_SIZE == Integer.BYTES) { 
      int[] intIds = childrenRef.getValue().getIntArray(0, childCountRef.getValue()); 
      ids = new long[intIds.length]; 
      for (int i = 0; i < intIds.length; i++) { 
       ids[i] = intIds[i]; 
      } 
     } 

     for (long id : ids) { 
      Window child = new Window(id); 
      X11.XTextProperty name = new X11.XTextProperty(); 
      x11.XGetWMName(display, child, name); 
      String value = name.value; 
      if (value != null) { 
       System.out.println(String.format("Found window %s free %s", value, name)); 
      } 
      if (value != null && pattern.matcher(value).matches()) { 
       windows.add(child); 
      } 
      x11.XFree(name.getPointer()); 
      windows.addAll(recurse(x11, display, child, pattern)); 
     } 
     return windows; 
    } 

    public static void main(String[] args) { 
     X11WindowFinder finder = new X11WindowFinder(); 
     while (true) { 
      finder.find(Pattern.compile(".*Firefox.*")); 
     } 
    } 

} 

Указатели в ЮНА появляются использовать Finalize(), чтобы освободить память т.е. com.sun.jna.Memory.finalize()

/** Properly dispose of native memory when this object is GC'd. */ 
protected void finalize() { 
    dispose(); 
} 

Так что, если я позвоню XFree(), я рискую, что его удвоит освобождение ... Это предположение правильно. Я могу найти несколько примеров JNA, особенно связанных с платформой X11.

+1

XLib не выделяет для вас 'XTextProperty'. Вы выделяете его с помощью 'new X11.XTextProperty()'. Таким образом, вы не должны «XFree». –

ответ

0

В итоге память удалось за кулисами JNA автоматически освобождается для вас по com.sun.jna.Memory.finalize(), когда JNA Java Object является сборкой мусора.

/** Properly dispose of native memory when this object is GC'd. */ 
protected void finalize() { 
    dispose(); 
} 

/** Free the native memory and set peer to zero */ 
protected synchronized void dispose() { 
    free(peer); 
    peer = 0; 
    allocatedMemory.remove(this); 
} 

Вы не должны вызывать XFree(), если вы рискуете «двойное открепление» ошибку, как описано в оригинальном вопросе "double free or corruption (fasttop)".

Это означает, что чтение man-страниц для функций X11 запутывает, когда вы реализуете JNA. Эти справочные страницы часто направляют вас на использование XFree для очистки возвращенных ресурсов.

1

Вы хотите освободить указатель в поле value структуры XTextProperty, а не самой структуры.

От XTextProperty man page:

To free the storage for the value field, use XFree. 

Из кода (обратите внимание, что value поле должно быть Pointer, а не String):

x11.XTextProperty name = new X11.XTextProperty(); 
x11.XGetWMName(display, child, name); 
// ... do some stuff 
x11.XFree(name.value); 
+0

Спасибо за ответ, пожалуйста, вы можете привести пример кода? Обратите внимание, что это привязки JNA на X11, поэтому подпись XFree (com.sun.jna.Pointer), поэтому не может видеть, как вы передавали бы что-либо, кроме x11.XFree (name.getPointer()) – Adam