JNAKernel32Library.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * Licensed to Elasticsearch under one or more contributor
  3. * license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright
  5. * ownership. Elasticsearch licenses this file to you under
  6. * the Apache License, Version 2.0 (the "License"); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.elasticsearch.bootstrap;
  20. import com.sun.jna.IntegerType;
  21. import com.sun.jna.Native;
  22. import com.sun.jna.NativeLong;
  23. import com.sun.jna.Pointer;
  24. import com.sun.jna.Structure;
  25. import com.sun.jna.WString;
  26. import com.sun.jna.win32.StdCallLibrary;
  27. import org.apache.logging.log4j.LogManager;
  28. import org.apache.logging.log4j.Logger;
  29. import org.apache.lucene.util.Constants;
  30. import java.util.ArrayList;
  31. import java.util.Arrays;
  32. import java.util.Collections;
  33. import java.util.List;
  34. /**
  35. * Library for Windows/Kernel32
  36. */
  37. final class JNAKernel32Library {
  38. private static final Logger logger = LogManager.getLogger(JNAKernel32Library.class);
  39. // Callbacks must be kept around in order to be able to be called later,
  40. // when the Windows ConsoleCtrlHandler sends an event.
  41. private List<NativeHandlerCallback> callbacks = new ArrayList<>();
  42. // Native library instance must be kept around for the same reason.
  43. private static final class Holder {
  44. private static final JNAKernel32Library instance = new JNAKernel32Library();
  45. }
  46. private JNAKernel32Library() {
  47. if (Constants.WINDOWS) {
  48. try {
  49. Native.register("kernel32");
  50. logger.debug("windows/Kernel32 library loaded");
  51. } catch (NoClassDefFoundError e) {
  52. logger.warn("JNA not found. native methods and handlers will be disabled.");
  53. } catch (UnsatisfiedLinkError e) {
  54. logger.warn("unable to link Windows/Kernel32 library. native methods and handlers will be disabled.");
  55. }
  56. }
  57. }
  58. static JNAKernel32Library getInstance() {
  59. return Holder.instance;
  60. }
  61. /**
  62. * Adds a Console Ctrl Handler.
  63. *
  64. * @return true if the handler is correctly set
  65. * @throws java.lang.UnsatisfiedLinkError if the Kernel32 library is not loaded or if the native function is not found
  66. * @throws java.lang.NoClassDefFoundError if the library for native calls is missing
  67. */
  68. boolean addConsoleCtrlHandler(ConsoleCtrlHandler handler) {
  69. boolean result = false;
  70. if (handler != null) {
  71. NativeHandlerCallback callback = new NativeHandlerCallback(handler);
  72. result = SetConsoleCtrlHandler(callback, true);
  73. if (result) {
  74. callbacks.add(callback);
  75. }
  76. }
  77. return result;
  78. }
  79. List<Object> getCallbacks() {
  80. return Collections.<Object>unmodifiableList(callbacks);
  81. }
  82. /**
  83. * Native call to the Kernel32 API to set a new Console Ctrl Handler.
  84. *
  85. * @return true if the handler is correctly set
  86. * @throws java.lang.UnsatisfiedLinkError if the Kernel32 library is not loaded or if the native function is not found
  87. * @throws java.lang.NoClassDefFoundError if the library for native calls is missing
  88. */
  89. native boolean SetConsoleCtrlHandler(StdCallLibrary.StdCallCallback handler, boolean add);
  90. /**
  91. * Handles consoles event with WIN API
  92. * <p>
  93. * See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683242%28v=vs.85%29.aspx
  94. */
  95. class NativeHandlerCallback implements StdCallLibrary.StdCallCallback {
  96. private final ConsoleCtrlHandler handler;
  97. NativeHandlerCallback(ConsoleCtrlHandler handler) {
  98. this.handler = handler;
  99. }
  100. public boolean callback(long dwCtrlType) {
  101. int event = (int) dwCtrlType;
  102. if (logger.isDebugEnabled()) {
  103. logger.debug("console control handler receives event [{}@{}]", event, dwCtrlType);
  104. }
  105. return handler.handle(event);
  106. }
  107. }
  108. /**
  109. * Memory protection constraints
  110. *
  111. * https://msdn.microsoft.com/en-us/library/windows/desktop/aa366786%28v=vs.85%29.aspx
  112. */
  113. public static final int PAGE_NOACCESS = 0x0001;
  114. public static final int PAGE_GUARD = 0x0100;
  115. public static final int MEM_COMMIT = 0x1000;
  116. /**
  117. * Contains information about a range of pages in the virtual address space of a process.
  118. * The VirtualQuery and VirtualQueryEx functions use this structure.
  119. *
  120. * https://msdn.microsoft.com/en-us/library/windows/desktop/aa366775%28v=vs.85%29.aspx
  121. */
  122. public static class MemoryBasicInformation extends Structure {
  123. public Pointer BaseAddress;
  124. public Pointer AllocationBase;
  125. public NativeLong AllocationProtect;
  126. public SizeT RegionSize;
  127. public NativeLong State;
  128. public NativeLong Protect;
  129. public NativeLong Type;
  130. @Override
  131. protected List<String> getFieldOrder() {
  132. return Arrays.asList("BaseAddress", "AllocationBase", "AllocationProtect", "RegionSize", "State", "Protect", "Type");
  133. }
  134. }
  135. public static class SizeT extends IntegerType {
  136. // JNA requires this no-arg constructor to be public,
  137. // otherwise it fails to register kernel32 library
  138. public SizeT() {
  139. this(0);
  140. }
  141. SizeT(long value) {
  142. super(Native.SIZE_T_SIZE, value);
  143. }
  144. }
  145. /**
  146. * Locks the specified region of the process's virtual address space into physical
  147. * memory, ensuring that subsequent access to the region will not incur a page fault.
  148. *
  149. * https://msdn.microsoft.com/en-us/library/windows/desktop/aa366895%28v=vs.85%29.aspx
  150. *
  151. * @param address A pointer to the base address of the region of pages to be locked.
  152. * @param size The size of the region to be locked, in bytes.
  153. * @return true if the function succeeds
  154. */
  155. native boolean VirtualLock(Pointer address, SizeT size);
  156. /**
  157. * Retrieves information about a range of pages within the virtual address space of a specified process.
  158. *
  159. * https://msdn.microsoft.com/en-us/library/windows/desktop/aa366907%28v=vs.85%29.aspx
  160. *
  161. * @param handle A handle to the process whose memory information is queried.
  162. * @param address A pointer to the base address of the region of pages to be queried.
  163. * @param memoryInfo A pointer to a structure in which information about the specified page range is returned.
  164. * @param length The size of the buffer pointed to by the memoryInfo parameter, in bytes.
  165. * @return the actual number of bytes returned in the information buffer.
  166. */
  167. native int VirtualQueryEx(Pointer handle, Pointer address, MemoryBasicInformation memoryInfo, int length);
  168. /**
  169. * Sets the minimum and maximum working set sizes for the specified process.
  170. *
  171. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms686234%28v=vs.85%29.aspx
  172. *
  173. * @param handle A handle to the process whose working set sizes is to be set.
  174. * @param minSize The minimum working set size for the process, in bytes.
  175. * @param maxSize The maximum working set size for the process, in bytes.
  176. * @return true if the function succeeds.
  177. */
  178. native boolean SetProcessWorkingSetSize(Pointer handle, SizeT minSize, SizeT maxSize);
  179. /**
  180. * Retrieves a pseudo handle for the current process.
  181. *
  182. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms683179%28v=vs.85%29.aspx
  183. *
  184. * @return a pseudo handle to the current process.
  185. */
  186. native Pointer GetCurrentProcess();
  187. /**
  188. * Closes an open object handle.
  189. *
  190. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211%28v=vs.85%29.aspx
  191. *
  192. * @param handle A valid handle to an open object.
  193. * @return true if the function succeeds.
  194. */
  195. native boolean CloseHandle(Pointer handle);
  196. /**
  197. * Retrieves the short path form of the specified path. See
  198. * <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa364989.aspx">{@code GetShortPathName}</a>.
  199. *
  200. * @param lpszLongPath the path string
  201. * @param lpszShortPath a buffer to receive the short name
  202. * @param cchBuffer the size of the buffer
  203. * @return the length of the string copied into {@code lpszShortPath}, otherwise zero for failure
  204. */
  205. native int GetShortPathNameW(WString lpszLongPath, char[] lpszShortPath, int cchBuffer);
  206. /**
  207. * Creates or opens a new job object
  208. *
  209. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682409%28v=vs.85%29.aspx
  210. *
  211. * @param jobAttributes security attributes
  212. * @param name job name
  213. * @return job handle if the function succeeds
  214. */
  215. native Pointer CreateJobObjectW(Pointer jobAttributes, String name);
  216. /**
  217. * Associates a process with an existing job
  218. *
  219. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms681949%28v=vs.85%29.aspx
  220. *
  221. * @param job job handle
  222. * @param process process handle
  223. * @return true if the function succeeds
  224. */
  225. native boolean AssignProcessToJobObject(Pointer job, Pointer process);
  226. /**
  227. * Basic limit information for a job object
  228. *
  229. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms684147%28v=vs.85%29.aspx
  230. */
  231. public static class JOBOBJECT_BASIC_LIMIT_INFORMATION extends Structure implements Structure.ByReference {
  232. public long PerProcessUserTimeLimit;
  233. public long PerJobUserTimeLimit;
  234. public int LimitFlags;
  235. public SizeT MinimumWorkingSetSize;
  236. public SizeT MaximumWorkingSetSize;
  237. public int ActiveProcessLimit;
  238. public Pointer Affinity;
  239. public int PriorityClass;
  240. public int SchedulingClass;
  241. @Override
  242. protected List<String> getFieldOrder() {
  243. return Arrays.asList("PerProcessUserTimeLimit", "PerJobUserTimeLimit", "LimitFlags", "MinimumWorkingSetSize",
  244. "MaximumWorkingSetSize", "ActiveProcessLimit", "Affinity", "PriorityClass", "SchedulingClass");
  245. }
  246. }
  247. /**
  248. * Constant for JOBOBJECT_BASIC_LIMIT_INFORMATION in Query/Set InformationJobObject
  249. */
  250. static final int JOBOBJECT_BASIC_LIMIT_INFORMATION_CLASS = 2;
  251. /**
  252. * Constant for LimitFlags, indicating a process limit has been set
  253. */
  254. static final int JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 8;
  255. /**
  256. * Get job limit and state information
  257. *
  258. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms684925%28v=vs.85%29.aspx
  259. *
  260. * @param job job handle
  261. * @param infoClass information class constant
  262. * @param info pointer to information structure
  263. * @param infoLength size of information structure
  264. * @param returnLength length of data written back to structure (or null if not wanted)
  265. * @return true if the function succeeds
  266. */
  267. native boolean QueryInformationJobObject(Pointer job, int infoClass, Pointer info, int infoLength, Pointer returnLength);
  268. /**
  269. * Set job limit and state information
  270. *
  271. * https://msdn.microsoft.com/en-us/library/windows/desktop/ms686216%28v=vs.85%29.aspx
  272. *
  273. * @param job job handle
  274. * @param infoClass information class constant
  275. * @param info pointer to information structure
  276. * @param infoLength size of information structure
  277. * @return true if the function succeeds
  278. */
  279. native boolean SetInformationJobObject(Pointer job, int infoClass, Pointer info, int infoLength);
  280. }