{"id":46200,"date":"2023-11-16T07:20:20","date_gmt":"2023-11-16T07:20:20","guid":{"rendered":"https:\/\/www.baeldung.com\/java-sharing-memory-between-jvms"},"modified":"2023-11-16T07:20:20","modified_gmt":"2023-11-16T07:20:20","slug":"sharing-memory-between-jvms","status":"publish","type":"post","link":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/2023\/11\/16\/sharing-memory-between-jvms\/","title":{"rendered":"Sharing Memory Between JVMs"},"content":{"rendered":"<p><img src=\"https:\/\/www.baeldung.com\/wp-content\/uploads\/2021\/09\/Java-4-Featured-1024x536.png\" class=\"webfeedsFeaturedVisual wp-post-image\" alt=\"\" decoding=\"async\" style=\"float: left; margin-right: 5px;\" loading=\"lazy\" srcset=\"https:\/\/www.baeldung.com\/wp-content\/uploads\/2021\/09\/Java-4-Featured-1024x536.png 1024w, https:\/\/www.baeldung.com\/wp-content\/uploads\/2021\/09\/Java-4-Featured-300x157.png 300w, https:\/\/www.baeldung.com\/wp-content\/uploads\/2021\/09\/Java-4-Featured-768x402.png 768w, https:\/\/www.baeldung.com\/wp-content\/uploads\/2021\/09\/Java-4-Featured-100x52.png 100w, https:\/\/www.baeldung.com\/wp-content\/uploads\/2021\/09\/Java-4-Featured.png 1200w\" sizes=\"(max-width: 580px) 100vw, 580px\" \/><\/p>\n<h2  id=\"bd-introduction\" data-id=\"introduction\">1. Introduction<\/h2>\n<div class=\"bd-anchor\" id=\"introduction\"><\/div>\n<p>In this tutorial, we&#8217;ll show how to share memory between two or more JVMs running on the same machine. This capability enables very fast inter-process communication since we can move data blocks around without any I\/O operation.<\/p>\n<h2 id=\"bd-how-shared-memory-works\" data-id=\"how-shared-memory-works\">2. How Shared Memory Works?<\/h2>\n<div class=\"bd-anchor\" id=\"how-shared-memory-works\"><\/div>\n<p>A process running in any modern operating system gets what&#8217;s called a virtual memory space. <strong>We call it <em>virtual<\/em> because, although it looks like a large, continuous, and private addressable memory space, in fact, it&#8217;s made of <em>pages<\/em> spread all over the physical RAM.<\/strong> Here, <em>page<\/em> is just OS slang for a block of contiguous memory, whose size range depends on the particular CPU architecture in use. For x86-84, a page can be as small as 4KB or as large as 1 GB.<\/p>\n<p>At a given time, only a fraction of this virtual space is actually mapped to physical pages. As time passes and the process starts to consume more memory for its tasks, the OS starts to allocate more physical pages and map them to the virtual space. When the demand for memory exceeds what&#8217;s physically available, the OS will start to swap out pages that are not being used at that moment to secondary storage to make room for the request.<\/p>\n<p><strong>A shared memory block behaves just like regular memory, but, in contrast with regular memory, it is not private to a single process<\/strong>. When a process changes the contents of any byte within this block, any other process with access to this same shared memory &#8220;sees&#8221; this change instantly.<\/p>\n<p>This is a list of common uses for shared memory:<\/p>\n<ul>\n<li>Debuggers (ever wondered how a debugger can inspect variables in another process?)<\/li>\n<li>Inter-process communication<\/li>\n<li>Read-only content sharing between processes (ex: dynamic library code)<\/li>\n<li>Hacks of all sorts ;^)<\/li>\n<\/ul>\n<h2  id=\"bd-shared_memory_and_memory_mapped_files\" data-id=\"shared_memory_and_memory_mapped_files\">3. Shared Memory and Memory-Mapped Files<\/h2>\n<div class=\"bd-anchor\" id=\"shared_memory_and_memory_mapped_files\"><\/div>\n<p><strong>A memory-mapped file, as the name suggests, is a regular file whose contents are directly mapped to a contiguous area in the virtual memory of a process<\/strong>. This means that we can read and\/or change its contents without explicit use of I\/O operations.\u00a0The OS will detect any writes to the mapped area and will schedule a background I\/O operation to persist the modified data.<\/p>\n<p>Since there are no guarantees on when this background operation will happen, the OS also offers a system call to flush any pending changes. This is important for use cases like database redo logs, but not needed for our inter-process communication (IPC, for short) scenario.<\/p>\n<p>Memory-mapped files are commonly used by database servers to achieve high throughput I\/O operations, but we can also use them to bootstrap a shared-memory-based IPC mechanism. <strong>The basic idea is that all processes that need to share data map the same file and, voil\u00e0, they now have a shared memory area<\/strong>.<\/p>\n<h2  id=\"bd-creating_memory_mapped_files_in_java\" data-id=\"creating_memory_mapped_files_in_java\">4. Creating Memory-Mapped Files in Java<\/h2>\n<div class=\"bd-anchor\" id=\"creating_memory_mapped_files_in_java\"><\/div>\n<p>In Java, we use the <a href=\"https:\/\/feeds.feedblitz.com\/~\/t\/0\/0\/baeldung\/~https:\/\/www.baeldung.com\/java-filechannel\"><em>FileChannel<\/em><\/a>&#8216;s <em>map()<\/em> method to map a region of a file into memory, which returns a <a href=\"https:\/\/feeds.feedblitz.com\/~\/t\/0\/0\/baeldung\/~https:\/\/www.baeldung.com\/java-mapped-byte-buffer\"><em>MappedByteBuffer<\/em> <\/a>that allows us to access its contents:<\/p>\n<pre><code class=\"language-java\">MappedByteBuffer createSharedMemory(String path, long size) {\r\n    try (FileChannel fc = (FileChannel)Files.newByteChannel(new File(path).toPath(),\r\n      EnumSet.of(\r\n        StandardOpenOption.CREATE,\r\n        StandardOpenOption.SPARSE,\r\n        StandardOpenOption.WRITE,\r\n        StandardOpenOption.READ))) {\r\n        return fc.map(FileChannel.MapMode.READ_WRITE, 0, size);\r\n    }\r\n    catch( IOException ioe) {\r\n        throw new RuntimeException(ioe);\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>The use of the <em>SPARSE<\/em> option here is quite relevant. <strong>As long the underlying OS and file system supports it, we can map sizable memory area without actually consuming disk space.<\/strong><\/p>\n<p>Now, let&#8217;s create a simple demo application. The <em>Producer<\/em> application will allocate a shared memory large enough to hold 64KB of data plus a SHA1 hash (20 bytes). Next, it will start a loop where it will fill the buffer with random data, followed by its SHA1 hash. We&#8217;ll repeat this operation continuously for 30 seconds and then exit:<\/p>\n<pre><code class=\"language-java\">\/\/ ... SHA1 digest initialization omitted\r\nMappedByteBuffer shm = createSharedMemory(&quot;some_path.dat&quot;, 64*1024 + 20);\r\nRandom rnd = new Random();\r\nlong start = System.currentTimeMillis();\r\nlong iterations = 0;\r\nint capacity = shm.capacity();\r\nSystem.out.println(&quot;Starting producer iterations...&quot;);\r\nwhile(System.currentTimeMillis() - start &lt; 30000) {\r\n    for (int i = 0; i &lt; capacity - hashLen; i++) {\r\n        byte value = (byte) (rnd.nextInt(256) &amp; 0x00ff);\r\n        digest.update(value);\r\n        shm.put(i, value);\r\n    }\r\n    \/\/ Write hash at the end\r\n    byte[] hash = digest.digest();\r\n    shm.put(capacity - hashLen, hash);\r\n    iterations++;\r\n}\r\nSystem.out.printf(&quot;%d iterations run\\n&quot;, iterations);\r\n<\/code><\/pre>\n<p>To test that we indeed can share memory, we&#8217;ll also create a <em>Consumer<\/em> app that will read the buffer&#8217;s content, compute its hash, and compare it with the <em>Producer<\/em>-generated one. We&#8217;ll repeat this process for 30 seconds. At each iteration, will also compute the buffer content&#8217;s hash and compare it with the one present at the buffer&#8217;s end:<\/p>\n<pre><code class=\"language-java\">\/\/ ... digest initialization omitted\r\nMappedByteBuffer shm = createSharedMemory(&quot;some_path.dat&quot;, 64*1024 + 20);\r\nlong start = System.currentTimeMillis();\r\nlong iterations = 0;\r\nint capacity = shm.capacity();\r\nSystem.out.println(&quot;Starting consumer iterations...&quot;);\r\nlong matchCount = 0;\r\nlong mismatchCount = 0;\r\nbyte[] expectedHash = new byte[hashLen];\r\nwhile (System.currentTimeMillis() - start &lt; 30000) {\r\n    for (int i = 0; i &lt; capacity - 20; i++) {\r\n        byte value = shm.get(i);\r\n        digest.update(value);\r\n    }\r\n    byte[] hash = digest.digest();\r\n    shm.get(capacity - hashLen, expectedHash);\r\n    if (Arrays.equals(hash, expectedHash)) {\r\n        matchCount++;\r\n    } else {\r\n        mismatchCount++;\r\n    }\r\n    iterations++;\r\n}\r\nSystem.out.printf(&quot;%d iterations run. matches=%d, mismatches=%d\\n&quot;, iterations, matchCount, mismatchCount);<\/code><\/pre>\n<p>To test our memory-sharing scheme, let&#8217;s start both programs at the same time. This is their output when running on a 3Ghz, quad-core Intel I7 machine:<\/p>\n<pre><code class=\"language-bash\"># Producer output\r\nStarting producer iterations...\r\n11722 iterations run\r\n# Consumer output\r\nStarting consumer iterations...\r\n18893 iterations run. matches=11714, mismatches=7179\r\n<\/code><\/pre>\n<p><strong>We can see that, in many cases, the consumer detects that the expected computed values are different<\/strong>. Welcome to the wonderful world of concurrency issues!<\/p>\n<h2  id=\"bd-synchronizing_shared_memory_access\" data-id=\"synchronizing_shared_memory_access\">5. Synchronizing Shared Memory Access<\/h2>\n<div class=\"bd-anchor\" id=\"synchronizing_shared_memory_access\"><\/div>\n<p><strong>The root cause for the issue we&#8217;ve seen is that we need to synchronize access to the shared memory buffer<\/strong>. The <em>Consumer<\/em> must wait for the <em>Producer<\/em> to finish writing the hash before it starts reading the data. On the other hand, the <em>Producer<\/em> also must wait for the <em>Consumer<\/em> to finish consuming the data before writing to it again.<\/p>\n<p>For a regular multithreaded application, solving this issue is no big deal. The standard library offers several synchronization primitives that allow us to control who can write to the shared memory at a given time.<\/p>\n<p>However, ours is a multi-JVM scenario, so none of those standard methods apply. So, what should we do? <strong>Well, the short answer is that we&#8217;ll have to cheat<\/strong>. We could resort to OS-specific mechanisms like semaphores, but this would hinder our application&#8217;s portability. Also, this implies using JNI or JNA, which also complicates things.<\/p>\n<p><strong>Enter <a href=\"https:\/\/feeds.feedblitz.com\/~\/t\/0\/0\/baeldung\/~https:\/\/www.baeldung.com\/java-unsafe\"><em>Unsafe<\/em><\/a><\/strong>. Despite its somewhat scary name, this standard library class offers exactly what we need to implement a simple lock mechanism: the <em>compareAndSwapInt()<\/em> method.<\/p>\n<p>This method implements an atomic test-and-set primitive that takes four arguments.<strong> Although not clearly stated in the documentation, it can target not only Java objects but also a raw memory address<\/strong>. For the latter, we pass <em>null<\/em> in the first argument, which makes it treat the\u00a0<em>offset <\/em>argument as a virtual memory address.<\/p>\n<p>When we call this method, it will first check the value at the target address and compare it with the\u00a0<em>expected<\/em> value. If they&#8217;re equal, then it will modify the location&#8217;s content to the new value and return <em>true<\/em> indicating success. If the value at the location is different from\u00a0<em>expected<\/em>, nothing happens, and the method returns <em>false.<\/em><\/p>\n<p><strong>More importantly, this atomic operation is guaranteed to work even in multicore architectures, which is a critical feature for synchronizing multiple executing threads.<\/strong><\/p>\n<p>Let&#8217;s create a <em>SpinLock<\/em> class that takes advantage of this method to implement a (very!) simple lock mechanism:<\/p>\n<pre><code class=\"language-java\">\/\/... package and imports omitted\r\npublic class SpinLock {\r\n    private static final Unsafe unsafe;\r\n    \/\/ ... unsafe initialization omitted\r\n    private final long addr;\r\n    public SpinLock(long addr) {\r\n        this.addr = addr;\r\n    }\r\n    public boolean tryLock(long maxWait) {\r\n        long deadline = System.currentTimeMillis() + maxWait;\r\n        while (System.currentTimeMillis() &lt; deadline ) {\r\n            if (unsafe.compareAndSwapInt(null, addr, 0, 1)) {\r\n                return true;\r\n            }\r\n        }\r\n        return false;\r\n    }\r\n    public void unlock() {\r\n        unsafe.putInt(addr, 0);\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>This implementation lacks key features, like checking whether it owns the lock before releasing it, but it will suffice for our purpose.<\/p>\n<p>Okay, so how do we get the memory address that we&#8217;ll use to store the lock status? This must be an address within the shared memory buffer so both processes can use it, but the <em>MappedByteBuffer<\/em> class does not expose the actual memory address.<\/p>\n<p>Inspecting the object that <em>map()<\/em> returns, we can see that it is a <em>DirectByteBuffer.<\/em> <strong>This class has a public method called <em>address()<\/em> that returns exactly what we want. Unfortunately, this class is package-private so we can&#8217;t use a simple cast to access this method.<\/strong><\/p>\n<p>To bypass this limitation, we&#8217;ll cheat a little again and use reflection to invoke this method:<\/p>\n<pre><code class=\"language-java\">private static long getBufferAddress(MappedByteBuffer shm) {\r\n    try {\r\n        Class&lt;?&gt; cls = shm.getClass();\r\n        Method maddr = cls.getMethod(&quot;address&quot;);\r\n        maddr.setAccessible(true);\r\n        Long addr = (Long) maddr.invoke(shm);\r\n        if (addr == null) {\r\n            throw new RuntimeException(&quot;Unable to retrieve buffer&#039;s address&quot;);\r\n        }\r\n        return addr;\r\n    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {\r\n        throw new RuntimeException(ex);\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>Here, we&#8217;re using <em>setAccessible()<\/em> to make the <em>address()<\/em> method callable through the <em>Method<\/em> handle. <strong>However, be aware that, from Java 17 onwards, this technique won&#8217;t work unless we explicitly use the runtime <em>\u2013add-opens<\/em> flag.<\/strong><\/p>\n<h2  id=\"bd-adding_synchronization\" data-id=\"adding_synchronization\">6. Adding Synchronization to <em>Producer<\/em> and\u00a0<em>Consumer<\/em><\/h2>\n<div class=\"bd-anchor\" id=\"adding_synchronization\"><\/div>\n<p>Now that we have a lock mechanism, let&#8217;s apply it to the <em>Producer<\/em> first. For the purposes of this demo, we&#8217;ll assume that the <em>Producer\u00a0<\/em>will always start before the\u00a0<em>Consumer.\u00a0<\/em>We need this so we can initialize the buffer, clearing its content including the area we&#8217;ll use with the <em>SpinLock:<\/em><\/p>\n<pre><code class=\"language-java\">public static void main(String[] args) throws Exception {\r\n    \/\/ ... digest initialization omitted\r\n    MappedByteBuffer shm = createSharedMemory(&quot;some_path.dat&quot;, 64*1024 + 20);\r\n    \/\/ Cleanup lock area \r\n    shm.putInt(0, 0);\r\n    long addr = getBufferAddress(shm);\r\n    System.out.println(&quot;Starting producer iterations...&quot;);\r\n    long start = System.currentTimeMillis();\r\n    long iterations = 0;\r\n    Random rnd = new Random();\r\n    int capacity = shm.capacity();\r\n    SpinLock lock = new SpinLock(addr);\r\n    while(System.currentTimeMillis() - start &lt; 30000) {\r\n        if (!lock.tryLock(5000)) {\r\n            throw new RuntimeException(&quot;Unable to acquire lock&quot;);\r\n        }\r\n        try {\r\n            \/\/ Skip the first 4 bytes, as they&#039;re used by the lock\r\n            for (int i = 4; i &lt; capacity - hashLen; i++) {\r\n                byte value = (byte) (rnd.nextInt(256) &amp; 0x00ff);\r\n                digest.update(value);\r\n                shm.put(i, value);\r\n            }\r\n            \/\/ Write hash at the end\r\n            byte[] hash = digest.digest();\r\n            shm.put(capacity - hashLen, hash);\r\n            iterations++;\r\n        }\r\n        finally {\r\n            lock.unlock();\r\n        }\r\n    }\r\n    System.out.printf(&quot;%d iterations run\\n&quot;, iterations);\r\n}\r\n<\/code><\/pre>\n<p>Compared to the unsynchronized version, there are just minor changes:<\/p>\n<ul>\n<li>Retrieve the memory address associated with the\u00a0<em>MappedByteBufer<\/em><\/li>\n<li>Create a\u00a0<em>SpinLock<\/em> instance using this address. The lock uses an\u00a0<em>int<\/em>, so it will take the four initial bytes of the buffer<\/li>\n<li>Use the <em>SpinLock<\/em> instance to protect the code that fills the buffer with random data and its hash<\/li>\n<\/ul>\n<p>Now, let&#8217;s apply similar changes to the\u00a0<em>Consumer\u00a0<\/em>side:<\/p>\n<pre><code class=\"language-java\">private static void main(String args[]) throws Exception {\r\n    \/\/ ... digest initialization omitted\r\n    MappedByteBuffer shm = createSharedMemory(&quot;some_path.dat&quot;, 64*1024 + 20);\r\n    long addr = getBufferAddress(shm);\r\n    System.out.println(&quot;Starting consumer iterations...&quot;);\r\n    Random rnd = new Random();\r\n    long start = System.currentTimeMillis();\r\n    long iterations = 0;\r\n    int capacity = shm.capacity();\r\n    long matchCount = 0;\r\n    long mismatchCount = 0;\r\n    byte[] expectedHash = new byte[hashLen];\r\n    SpinLock lock = new SpinLock(addr);\r\n    while (System.currentTimeMillis() - start &lt; 30000) {\r\n        if (!lock.tryLock(5000)) {\r\n            throw new RuntimeException(&quot;Unable to acquire lock&quot;);\r\n        }\r\n        try {\r\n            for (int i = 4; i &lt; capacity - hashLen; i++) {\r\n                byte value = shm.get(i);\r\n                digest.update(value);\r\n            }\r\n            byte[] hash = digest.digest();\r\n            shm.get(capacity - hashLen, expectedHash);\r\n            if (Arrays.equals(hash, expectedHash)) {\r\n                matchCount++;\r\n            } else {\r\n                mismatchCount++;\r\n            }\r\n            iterations++;\r\n        } finally {\r\n            lock.unlock();\r\n        }\r\n    }\r\n    System.out.printf(&quot;%d iterations run. matches=%d, mismatches=%d\\n&quot;, iterations, matchCount, mismatchCount);\r\n}\r\n<\/code><\/pre>\n<p>With those changes, we can now run both sides and compare them with the previous result:<\/p>\n<pre><code class=\"language-bash\"># Producer output\r\nStarting producer iterations...\r\n8543 iterations run\r\n# Consumer output\r\nStarting consumer iterations...\r\n8607 iterations run. matches=8607, mismatches=0\r\n<\/code><\/pre>\n<p><strong>As expected, the reported iteration count will be lower compared to the non-synchronized version<\/strong>. The main reason is that we spend most part of the time within the critical section of the code holding the lock. Whichever program holding the lock prevents the other side from doing anything.<\/p>\n<p>If we compare the average iteration count reported from the first case, it will be approximately the same as the sum of iterations we got this time. This shows that the overhead added by the lock mechanism itself is minimal.<\/p>\n<h2  id=\"bd-conclusion\" data-id=\"conclusion\">6. Conclusion<\/h2>\n<div class=\"bd-anchor\" id=\"conclusion\"><\/div>\n<p>In this tutorial, we&#8217;ve explored how to use share a memory area between two JVMs running on the same machine. We can use the technique presented here as the foundation for high-throughput, low-latency inter-process communication libraries.<\/p>\n<p>As usual, all code is available <a href=\"https:\/\/feeds.feedblitz.com\/~\/t\/0\/0\/baeldung\/~https:\/\/github.com\/eugenp\/tutorials\/tree\/master\/core-java-modules\/core-java-sun\">over on GitHub<\/a>.<\/p>\n<p><Img align=\"left\" border=\"0\" height=\"1\" width=\"1\" alt=\"\" style=\"border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;\" hspace=\"0\" src=\"https:\/\/feeds.feedblitz.com\/~\/i\/834339341\/0\/baeldung\"><\/p>\n<div style=\"clear:both;padding-top:0.2em;\"><a title=\"Like on Facebook\" href=\"https:\/\/feeds.feedblitz.com\/_\/28\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/fblike20.png\" style=\"border:0;margin:0;padding:0;\"><\/a>&#160;<a title=\"Pin it!\" href=\"https:\/\/feeds.feedblitz.com\/_\/29\/834339341\/baeldung,https%3A%2F%2Fwww.baeldung.com%2Fwp-content%2Fuploads%2F2021%2F09%2FJava-4-Featured-1024x536.png\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/pinterest20.png\" style=\"border:0;margin:0;padding:0;\"><\/a>&#160;<a title=\"Tweet This\" href=\"https:\/\/feeds.feedblitz.com\/_\/24\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/twitter20.png\" style=\"border:0;margin:0;padding:0;\"><\/a>&#160;<a title=\"Subscribe by email\" href=\"https:\/\/feeds.feedblitz.com\/_\/19\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/email20.png\" style=\"border:0;margin:0;padding:0;\"><\/a>&#160;<a title=\"Subscribe by RSS\" href=\"https:\/\/feeds.feedblitz.com\/_\/20\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/rss20.png\" style=\"border:0;margin:0;padding:0;\"><\/a>&#160;<a rel=\"NOFOLLOW\" title=\"View Comments\" href=\"https:\/\/www.baeldung.com\/java-sharing-memory-between-jvms#respond\"><img decoding=\"async\" height=\"20\" style=\"border:0;margin:0;padding:0;\" src=\"https:\/\/assets.feedblitz.com\/i\/comments20.png\"><\/a>&#160;<a title=\"Follow Comments via RSS\" href=\"https:\/\/www.baeldung.com\/java-sharing-memory-between-jvms\/feed\"><img decoding=\"async\" height=\"20\" style=\"border:0;margin:0;padding:0;\" src=\"https:\/\/assets.feedblitz.com\/i\/commentsrss20.png\"><\/a>&#160;<\/div>\n\n<h2><b>Commercials Cooperation Advertisements:<\/b><\/h2>\r\n<p><br>(1) IT Teacher IT Freelance<br> <\/p>\r\n<a href=https:\/\/itteacheritfreelance.hk\/wordpress><img src=http:\/\/gamefootballmobileanimeiphone.com\/wp-content\/uploads\/2023\/09\/ITTeacherITFreelance-Website.png alt=IT\u96fb\u8166\u88dc\u7fd2 java\u88dc\u7fd2 \u70ba\u5927\u5bb6\u914d\u5c0d\u96fb\u8166\u88dc\u7fd2,IT freelance, \u79c1\u4eba\u8001\u5e2b, PHP\u88dc\u7fd2,CSS\u88dc\u7fd2,XML,Java\u88dc\u7fd2,MySQL\u88dc\u7fd2,graphic design\u88dc\u7fd2,\u4e2d\u5c0f\u5b78ICT\u88dc\u7fd2,\u4e00\u5c0d\u4e00\u79c1\u4eba\u88dc\u7fd2\u548cFreelance\u81ea\u7531\u5de5\u4f5c\u914d\u5c0d\u3002\/><\/a><p><a href=https:\/\/itteacheritfreelance.hk\/wordpress\/index.php\/findteacher>\u7acb\u523b\u8a3b\u518a\u53ca\u5831\u540d\u96fb\u8166\u88dc\u7fd2\u8ab2\u7a0b\u5427! <\/a><br>\r\n\r\n\u7535\u5b50\u8ba1\u7b97\u673a -\u6559\u80b2 -IT \u96fb\u8166\u73ed\u201d ( IT\u96fb\u8166\u88dc\u7fd2 ) \u63d0\u4f9b\u4e00\u500b\u65b9\u4fbf\u7684\u7535\u5b50\u8ba1\u7b97\u673a \u6559\u80b2\u5e73\u53f0, \u70ba\u5927\u5bb6\u914d\u5c0d\u4fe1\u606f\u6280\u672f, \u96fb\u8166 \u8001\u5e2b, IT freelance \u548c programming expert. \u8b93\u5927\u5bb6\u65b9\u4fbf\u5730\u5c31\u80fd\u627e\u5230\u5408\u9069\u7684\u96fb\u8166\u88dc\u7fd2, \u96fb\u8166\u73ed, \u5bb6\u6559, \u79c1\u4eba\u8001\u5e2b.  <br>\r\n\r\nWe are a education and information platform which you can find a IT private tutorial teacher or freelance. <br>\r\n\r\nAlso we provide different information about information technology, Computer, programming, mobile, Android, apple, game, movie, anime, animation\u2026 \r\n<\/p>\n<p><br>(2) ITSec<br> <\/p><a href=https:\/\/itsec.vip><img src=http:\/\/gamefootballmobileanimeiphone.com\/wp-content\/uploads\/2023\/09\/ITSec-Main-Promotion-Image.png alt= https:\/\/itsec.vip\/\r\nSecure Your Computers from Cyber Threats and mitigate risks with professional services to defend Hackers.  \r\nITSec provide IT Security and Compliance Services, including IT Compliance Services, Risk Assessment, IT Audit, Security Assessment and Audit, ISO 27001 Consulting and Certification, GDPR Compliance Services, Privacy Impact Assessment (PIA), Penetration test, Ethical Hacking, Vulnerabilities scan, IT Consulting, Data Privacy Consulting, Data Protection Services, Information Security Consulting, Cyber Security Consulting, Network Security Audit, Security Awareness Training.\/><\/a> \r\n<br><br> \r\n<p><a href=https:\/\/itsec.vip>www.ITSec.vip<\/a> <br> <br> \r\n<p><a href=https:\/\/sraa.com.hk>www.Sraa.com.hk<\/a> <br> <br> \r\n<p><a href=https:\/\/itsec.hk>www.ITSec.hk<\/a> <br> <br> \r\n<p><a href=https:\/\/penetrationtest.hk>www.Penetrationtest.hk<\/a> <br> <br> \r\n<p><a href=https:\/\/itseceu.uk>www.ITSeceu.uk<\/a> <br> <br> \r\nSecure Your Computers from Cyber Threats and mitigate risks with professional services to defend Hackers. <br><br>\r\nITSec provide IT Security and Compliance Services, including IT Compliance Services, Risk Assessment, IT Audit, Security Assessment and Audit, ISO 27001 Consulting and Certification, GDPR Compliance Services, Privacy Impact Assessment (PIA), Penetration test, Ethical Hacking, Vulnerabilities scan, IT Consulting, Data Privacy Consulting, Data Protection Services, Information Security Consulting, Cyber Security Consulting, Network Security Audit, Security Awareness Training. \r\n<br><br>Contact us right away. <br><br>Email (Prefer using email to contact us): <br>SalesExecutive@ITSec.vip<\/p>","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/www.baeldung.com\/wp-content\/uploads\/2021\/09\/Java-4-Featured-1024x536.png\" class=\"webfeedsFeaturedVisual wp-post-image\" alt=\"\"><\/p>\n<p>Learn how to use share a memory area between two JVMs running on the same machine.<\/p>\n<div><a title=\"Like on Facebook\" href=\"https:\/\/feeds.feedblitz.com\/_\/28\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/fblike20.png\"><\/a>\u00a0<a title=\"Pin it!\" href=\"https:\/\/feeds.feedblitz.com\/_\/29\/834339341\/baeldung,https%3A%2F%2Fwww.baeldung.com%2Fwp-content%2Fuploads%2F2021%2F09%2FJava-4-Featured-1024x536.png\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/pinterest20.png\"><\/a>\u00a0<a title=\"Tweet This\" href=\"https:\/\/feeds.feedblitz.com\/_\/24\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/twitter20.png\"><\/a>\u00a0<a title=\"Subscribe by email\" href=\"https:\/\/feeds.feedblitz.com\/_\/19\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/email20.png\"><\/a>\u00a0<a title=\"Subscribe by RSS\" href=\"https:\/\/feeds.feedblitz.com\/_\/20\/834339341\/baeldung\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/rss20.png\"><\/a>\u00a0<a rel=\"NOFOLLOW\" title=\"View Comments\" href=\"https:\/\/www.baeldung.com\/java-sharing-memory-between-jvms#respond\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/comments20.png\"><\/a>\u00a0<a title=\"Follow Comments via RSS\" href=\"https:\/\/www.baeldung.com\/java-sharing-memory-between-jvms\/feed\"><img decoding=\"async\" height=\"20\" src=\"https:\/\/assets.feedblitz.com\/i\/commentsrss20.png\"><\/a>\u00a0<\/div>\n","protected":false},"author":1406,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"site-container-style":"default","site-container-layout":"default","site-sidebar-layout":"default","disable-article-header":"default","disable-site-header":"default","disable-site-footer":"default","disable-content-area-spacing":"default","footnotes":""},"categories":[22],"tags":[61,122,127,129,124,128,125,132,131,133,126,130,123,66,94,88,97,56,64,65,60,112,40,75,95,104,33,120,105,101,98,115,30,29,41,86,70,69,68,72,71,26,118,108,87,46,55,48,52,54,51,50,83,62,58,57,14446,109,35,59,63,85,79,82,96,80,27,81,114,44,42,43,45,38,39,110,117,100,111,116,73,89,90,92,91,93,84,78,37,102,34,36,77,67,74,99,113,119,28,121,32,47,49,53,103,31,76],"class_list":["post-46200","post","type-post","status-publish","format-standard","hentry","category-mobile","tag-airpods","tag-anime","tag-anime-characters","tag-anime-cosplay","tag-anime-edits","tag-anime-merchandise","tag-anime-movies","tag-anime-news","tag-anime-recommendations","tag-anime-reviews","tag-anime-series","tag-anime-streaming","tag-animes","tag-app-store","tag-app-store-samsung","tag-appgallery","tag-appgallery-oneplus","tag-apple","tag-apple-music","tag-apple-tv","tag-apple-watch","tag-bbc-sport","tag-best-mobile-games","tag-bixby","tag-bixby-xiaomi","tag-champions-league","tag-cyberpunk","tag-cyberpunk-2077","tag-fantasy-football","tag-fifa","tag-football","tag-formula-1","tag-fortnite","tag-free-fire","tag-free-mobile-games","tag-freebuds-pro","tag-galaxy-a52","tag-galaxy-note-20","tag-galaxy-s21","tag-galaxy-watch-4","tag-galaxy-z-fold-3","tag-game","tag-games","tag-golf","tag-harmonyos","tag-how-to-backup-iphone","tag-how-to-factory-reset-iphone","tag-how-to-reset-iphone","tag-how-to-restore-iphone","tag-how-to-unlock-iphone","tag-how-to-unlock-iphone-5","tag-how-to-unlock-iphone-6","tag-huawei","tag-ios","tag-ipad","tag-iphone","tag-jvm","tag-live-soccer","tag-lol","tag-macbook","tag-macos","tag-mate-40-pro","tag-mi-11-lite","tag-mi-home-security-camera-basic-1080p","tag-mi-home-security-camera-basic-1080p-huawei","tag-mi-smart-band-6","tag-minecraft","tag-miui","tag-mlb-scores","tag-mobile-game-design","tag-mobile-game-development","tag-mobile-game-marketing","tag-mobile-game-monetization","tag-mobile-games","tag-mobile-gaming","tag-nba-scores","tag-nba-standings","tag-nfl","tag-nfl-scores","tag-nhl-scores","tag-one-ui","tag-oneplus","tag-oneplus-9-pro","tag-oneplus-buds-pro","tag-oneplus-nord-ce-5g","tag-oxygenos","tag-p40-pro-plus","tag-poco-x3-pro","tag-pokemon","tag-premier-league","tag-pubg","tag-pubg-mobile","tag-redmi-note-10-pro","tag-samsung","tag-samsung-pay","tag-soccer","tag-sports","tag-steam","tag-steeam","tag-top-10-anime","tag-valorant","tag-when-do-the-iphone-7-come-out","tag-when-does-the-iphone-7-come-out","tag-when-is-the-iphone-7-coming-out","tag-world-cup","tag-xbox-series-x","tag-xiaomi"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/posts\/46200","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/users\/1406"}],"replies":[{"embeddable":true,"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/comments?post=46200"}],"version-history":[{"count":0,"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/posts\/46200\/revisions"}],"wp:attachment":[{"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/media?parent=46200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/categories?post=46200"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gamefootballmobileanimeiphone.com\/index.php\/wp-json\/wp\/v2\/tags?post=46200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}