ãåãã®ããã«ãJavaã®ãããªä»»æã®èšèªã§æžãããšãã§ããjavistaã®æåã®æã¯ã¬ããŒãžã³ã¬ã¯ã¿ãŒãšJITã³ã³ãã€ã©ãŒãæžãããšã§ãã ããšãã°ã管çãããã³ãŒããããã·ã³ã³ãŒããã¢ã»ã³ãã©ãŒãçŽæ¥æäœããã«ã¯ã©ãããã°ããã§ããããã
ããã«ããã®èšäºã¯CïŒã®å°ããªäŸã«ãªããŸãã ããæç¹ã§ãåžžã«1ã€ã®JavaãåŠç¿ã§ããããã§ã¯ãªãããšãæããã«ãªããŸããã åçèšèªã®ç§å Žã¯äžè¬çãªçè«ã䜿çšããå®éã«ã¯åæ§ã®åé¡ã®æ çµã¿å
ã§äœæ¥ããŸãã ããªãã®äœåã宣äŒããæãç°¡åãªæ¹æ³ã¯ãããªãã®é£äººãã©ã®ããã«ããã«ããããèŠãŠãèªåã«è¯ããã®ãã³ããŒããããšã§ãã
次ã«ãã¢ã»ã³ãã©ãšãã·ã³ã³ãŒãã«ã€ããŠèª¬æããŸãã ãããå¿
èŠãªçç±ã¯æªè§£æ±ºã®åé¡ã§ãã ããšãã°ãMeltdownã«ã€ããŠå€ãã®ããšãèããŠããã®ããã®çŽ æµãªAPIãæžããããšæããŸã:-)ãŸããOracleã¯ç¥ã§ã¯ãªãããšãå¿ããªãã§ãã ãããäžéšã®æšæºã¡ãœããã¯ãSDKãªã©ã«ãããã®ãããé©åã«å®è£
ã§ããŸãã -åžžã«æãäžãããã®ããããŸãïŒ
åé¡ã«ã¯2ã€ã®ã¬ãã«ããããŸãã
- Javaã³ãŒãã§ãã·ã³ã³ãŒããŸãã¯x86ã¢ã»ã³ãã©ãŒãçŽæ¥ã€ã³ã©ã€ã³åããããšã¯ã§ããŸããïŒ
__asm()
æ§é ãæ¿å
¥ããŸãïŒ - ããããçŽæ¥å®è¡ããããšã¯ã§ããŸããïŒãã ããæ§æããªãå Žåããã®åé¡ã«å°éããããšã¯å°é£ã§ãïŒ
ãã ããåŸã§èª¬æããããã¯ãæªçšããããšãã§ããŸãã
çŽ æŽãªãªãã·ã§ã³ïŒå®è¡ããŠãã ããïŒ
ãåç¥ã®ããã«ãJNIã䜿ââçšããŠãã€ãã£ãã³ãŒããå®è¡ã§ããŸãã
ã€ãŸããC ++ã§ã¯ããã·ã³ã³ãŒããéãã«åçã«çæããŠãããã«ã§ããŸãã
ãããè¡ãã«ã¯ãåæã«æžã蟌ã¿ãšå®è¡ãå¯èœãªã¡ã¢ãªã»ã°ã¡ã³ããäœæããå¿
èŠããããŸãã
VirtualAllocExã䜿çšããWindowsã®äŸã次ã«ç€ºããŸãïŒ posixã«ã¯mprotectïŒ2ïŒããããŸãããç§ã¯é¢åã§ãïŒã
圌ãäœãããŠããããçè§£ããŠã¿ãŠãã ããã PAGE_EXECUTE_READWRITE
ããªãå Žåããã®ã³ãŒãã¯Windowsã®ããŒã¿å®è¡é²æ¢ãå³åº§ã«æã¡è² ãããŸãã
#include <stdio.h> #include <windows.h> typedef unsigned char byte; int arg1; int arg2; int res1; typedef void (*pfunc)(void); union funcptr { pfunc x; byte* y; }; int main( void ) { byte* buf = (byte*)VirtualAllocEx( GetCurrentProcess(), 0, 1<<16, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if( buf==0 ) return 0; byte* p = buf; *p++ = 0x50; // push eax *p++ = 0x52; // push edx *p++ = 0xA1; // mov eax, [arg2] (int*&)p[0] = &arg2; p+=sizeof(int*); *p++ = 0x92; // xchg edx,eax *p++ = 0xA1; // mov eax, [arg1] (int*&)p[0] = &arg1; p+=sizeof(int*); *p++ = 0xF7; *p++ = 0xEA; // imul edx *p++ = 0xA3; // mov [res1],eax (int*&)p[0] = &res1; p+=sizeof(int*); *p++ = 0x5A; // pop edx *p++ = 0x58; // pop eax *p++ = 0xC3; // ret funcptr func; func.y = buf; arg1 = 123; arg2 = 321; res1 = 0; func.x(); // call generated code printf( "arg1=%i arg2=%i arg1*arg2=%i func(arg1,arg2)=%i\n", arg1,arg2,arg1*arg2,res1 ); }
ãã¡ãããæäœæ¥ã§è¡ãããšã¯æãè³¢æãªèãã§ã¯ãªããäœããã®AsmJitããã©ãã°ããå¿
èŠããããŸãã æ¬¡ã«ãJavaã³ãŒãããç¹å®ã®ããŒã¿ã転éãããããã¡ãã©ã®ããã«åãããããããŠããã-ããŒã«ããŸããïŒ
ããã§ã®åé¡ã¯ãã€ã³ã©ã€ã³ããããã¶ããã倧èãªæ©èœãæåŸ
ããããšã§ãã åŒã³åºãã®ã³ã³ããã¹ãå
šäœã«ã¢ã¯ã»ã¹ããããã«SDKããããŸããŸãªã·ã¹ãã èŠçŽ ãååŸããããšæããŸãã ããªãã¯ããããèªåã§ãããè¡ãããšãã§ããŸã-ããããé·ãéãçã¿ã䌎ãã 幞ããªããšã«ããã¹ãŠããã§ã«ç§ãã¡ã®åã«çãŸããŠããŸãã
Javaãã€ãã£ãã€ã³ã¿ãŒãã§ã€ã¹
JNIã¯åŒãç¶ã䜿çšã§ããŸãããå¥ã®æ¹æ³ã§äœ¿çšã§ããŸãã
次ã®ãããªã¯ã©ã¹ããããšããŸãããïŒ
public class MyJNIClass { public native void printVersion(); }
ã¢ã€ãã¢ã¯ãJNIåœåèŠåã«åŸã£ãŠãã£ã©ã¯ã¿ãŒã«ååãä»ããããšã§ããããããã°ãããèªäœããã¹ãŠãè¡ããŸãã ãã®å Žåã Java_MyJNIClass_printVersion
ãããªãã®ã«ãªããŸãã
ã·ã³ãã«ã¯ä»ã®ç¿»èš³åäœããèŠããå¿
èŠããããŸããããã¯ã global
ãã£ã¬ã¯ãã£ãã䜿çšããŠNASMã§ããŸãã¯publicã䜿çšããŠFASMã§å®è¡ã§ããŸãã
asmèªäœã¯ã䜿çšããã¢ãŒããã¯ãã£ã®åŒã³åºãèŠçŽãçè§£ããŠäœæããå¿
èŠããããŸãïŒåŒæ°ã¯ã¬ãžã¹ã¿ãã¹ã¿ãã¯ãä»ã®ã¡ã¢ãªæ§é ãªã©ã«ãããŸãïŒã 颿°ã«å°éããæåã®åŒæ°ã¯JNIEnv
ãžã®ãã€ã³ã¿ãŒã«ãªããJNI颿°ã®ããŒãã«ãžã®ãã€ã³ã¿ãŒã«ãªããŸãã
ããšãã°ãx86_64ã®äžã®NASMã¯æ¬¡ã®ããã«ãªããŸãã
global Java_MyJNIClass_printVersion section .text Java_MyJNIClass_printVersion: mov rax, [rdi] call [rax + 8*4] ; pointer size in x86_64 * index of GetVersion ...
GetVersion
ããžãã¯ã€ã³ããã¯ã¹ã¯GetVersion
ã§ããïŒ éåžžã«ç°¡åïŒãããã¯ããã¥ã¡ã³ãã«ãªã¹ããããŠããŸã ã
GetVersion
説æã¯æ¬¡ã®ããã«ãªããŸãã
GetVersion jint GetVersion(JNIEnv *env); Returns the version of the native method interface. LINKAGE: Index 4 in the JNIEnv interface function table. PARAMETERS: env: the JNI interface pointer. RETURNS: Returns the major version number in the higher 16 bits and the minor version number in the lower 16 bits. In JDK/JRE 1.1, GetVersion() returns 0x00010001. In JDK/JRE 1.2, GetVersion() returns 0x00010002. In JDK/JRE 1.4, GetVersion() returns 0x00010004. In JDK/JRE 1.6, GetVersion() returns 0x00010006.
ã芧ã®ãšããã颿°ããŒãã«ã¯åãªããã€ã³ã¿ã®é
åã®äžçš®ã§ãã ãã¡ããããããã®ã€ã³ããã¯ã¹ã«ã¿ãŒã²ããã¢ãŒããã¯ãã£ã®ãã€ã³ã¿ã®ãµã€ãºãæããããšãå¿ããŠã¯ãªããŸããã
2çªç®ã®åŒæ°ã¯ã颿°ãåŒã³åºããã¯ã©ã¹ãŸãã¯ãªããžã§ã¯ããžã®åç
§ã§ãã 以äžã®åŒæ°ã¯ãã¹ãŠãJavaã³ãŒãã§native
ãšããŠå®£èšãããã¡ãœããã®ãã©ã¡ãŒã¿ãŒã§ãã
次ã«ãã¢ã»ã³ãã©ãŒãããªããžã§ã¯ããã¢ã»ã³ãã«ããå¿
èŠããããŸãnasm -f elf64 -o GetVersion.o GetVersion.asm
ãªããžã§ã¯ãã³ã¬ã¯ã·ã§ã³-ã©ã€ãã©ãªããïŒ gcc -shared -z noexecstack -o libGetVersion.so GetVersion.o
æåŸã«ããã¡ã€ã«èªäœãåéããŸãïŒ javac MyJNIClass.java
ããè€éãªæäœãå®è¡ã§ããŸãã é
åèŠçŽ ã远å ããäŸã次ã«ç€ºããŸã ã
ãããŠããã¹ãŠãããŸãããããã§ãããç§ã¯ããã€ãã®ãã®ã欲ããã§ãã
ãŸããJavaã§ã³ãŒãã£ã³ã°ããå Žåãã¢ã»ã³ãã©ãŒãäœæããããã®éçãã§ãã¯ãåããçŸããæ§æïŒãã®å Žåã¯ã©ãããæå³ã§ãïŒãå¿
èŠã§ãã ç§ã¯é髪ã§ãIDEã®ãªãŒãã³ã³ããªãŒãã§ã¬ãžã¹ã¿ãéžæããŸãã1æåã§å°å°ãããããšãæããŸããã ããŠãå°ãªããšãJava APIã«ããŸãããã
第äºã«ãã³ãŒãã®é£ã«æã§ã©ã€ãã©ãªãã¢ã»ã³ãã«ããããšã¯ãå§ãã§ããŸããã ããŠããã¡ã€ã«ã1ã€ãã€åéããã«ã¯-äžçªäžã§ãã ãã®ãããªããšãæ°ã«ããªãã€ã³ãã©ã¹ãã©ã¯ãã£ãå¿
èŠã§ãã ããšãã°ãasmã³ãŒããã€ã³ã©ã€ã³ãMavenã®ãã©ã°ã€ã³ããŸãã¯å€æŽãããJDKã®äžéšãšããŠé
åžããŸãã
第äžã«ãå€ãã®ç°ãªã衚çŸããããããæœè±¡åãšããŠã¢ã»ã³ãã©ãéžæãã䟡å€ããããã©ããã¯æããã§ã¯ãããŸããã
峿žé€š
ããã«ãJavaã®ãã·ã³ã³ãŒãã«æºãã£ãŠããOracleã®ç·æ§ã«æçŽãæžããŠãçããåãåããŸããã圌ãã¯éåžžã®çŸããã©ã€ãã©ãªãç¥ããªãã®ã§ãã
ãã ããGoogleã«ã¢ã¯ã»ã¹ããå¿
èŠããããŸããæ ãè
ã§ã¯ãããŸããã ãjava call x86 assembly libraryãããŒã¯ãŒãã䜿çšããŠãçµæãçæ³ããŸãã
çµæã¯ãã©ã€ãã©ãªã®èгç¹ããããã¹ãŠãæ¬åœã«æªãããšã瀺ããŠããŸãã The Machine Level Javaãå«ãããã€ãã®æªå®æã®ãã®ãGoogleã§æ€çŽ¢ããŸããã
ãããŠãããã«ã¯çŸããAPIãããããŸãïŒJavaã®æ§é ã䜿çšãããšãã®çŸããïŒã
public class SimpleNativeDemo extends X86InlineAssembly // X86InlineAssembly is a successor of InlineAssembly { static
æ§æïŒJavaããŒãµãŒã倿Žããã«ïŒãšå®è¡æ¹æ³ã®äž¡æ¹ãåŸãããŸãã
ããã§ã®äž»ãªåé¡ã¯ãå
éšãéåžžã«è€éãªã³ãŒãã§ããããµããŒãããå¿
èŠãããããšã§ãã Javaã§ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã å
šäœãäœæãããããžã§ã¯ãã§ããjEmbryOSã®äžéšã§ãã ãããŠãèŠããšããããã®ãããžã§ã¯ãã¯ããŸã掻çºã§ã¯ãããŸããïŒ2014å¹Žã®ææ°ã®æçš¿ããã空ã®ãã©ãŒã©ã ã§ããSourceforgeïŒããã³GitHubããã®ä»ã®äººæ°ã®ããææ°ã®ãã¹ãã£ã³ã°ãµãŒãã¹ïŒã«ã¯ãŸã ãããŸããã coã®æåŸã®éã¯ãSourceforgeã®2015ãªãªãŒã¹ã§ã¯ã©ã€ã»ã³ã¹ãã¡ã€ã«ããªãããšã§ããã©ã€ã»ã³ã¹ãªãã§ã¯ã³ãŒãã䜿çšã§ããŸããïŒãã®ãããªèªã¿åãå°çšã³ãŒããäœæããããã©ã«ãã®èäœæš©èŠåãé©çšãããŸãïŒã
ããŠãããŸããããŸããã§ããã ããããå°æ¥çã«ã¯ãã¢ã€ãã¢ãæç¢ºãªã®ã§ãèªåã§æžãããšãã§ããŸãã
çæ§
ãã®æ©äŒã«ãã¬ããŒãå
šäœãããã«ãããŸãïŒ
äŒè°ã«è¡ã䟡å€ãããå Žåããããã¯ã¬ããŒãã§ãã Volker zhzhotã
ã¡ãªã¿ã«ã圌ã¯ããã·ãã«ã¹ã¯ã®æ¬¡ã®JBreakã«åå ã ã ã¯ã©ã¹ããŒã¿ã®å
±æã«ã€ããŠå¥ã®ã¢ããŒãªã³ã°ãè¡ããŸãã
ã€ãŸããOpenJDKã«ã¯ããžãã¯ãã¡ã€ã«src/share/vm/classfile/vmSymbols.hpp
ãŸãã ãªã³ã¯ã§ãã©ãŠã¶ã§éãã ãã§ããã¹ãŠãçè§£ã§ããŸãã ç¹å®ã®ã¡ãœããããã£ããããããããã¢ã»ã³ãã©ãŒã§çœ®ãæããããšãã§ããŸãã ãã¡ããããããã®å€æŽãå ããŠOpenJDKãåæ§ç¯ããŸãã
ç§èŠãæ¬åœã«ããŸãããã°ããããè¡ãããšãã§ããŸãïŒ __asm("ret")
ãããªæ§é äœãžã®åŒã³åºãããã£ãããã.javaã¯ã©ã¹ã®ããªããã»ããµãäœæãããããããçµã¿èŸŒã¿é¢æ°ã®ããããçæããOpenJDKãèªåçã«åæ§ç¯ããŸãã
ã©ãããŠãã®æ±ºå®ãç§ã«ã¯ããŸã楜ãããªãããã«èŠããã®ã§ããïŒ ãŸããçµã¿èŸŒã¿é¢æ°ã®å€æŽã«ãããOpenJDKã®éèŠãªéšåãåæ§ç¯ãããŸãã ã ããããè¶ã飲ãã§ãéåžžã«é »ç¹ã«å«ç
ããªããã°ãªããŸãã æ²ãã¿ã«é
ã ã¹ããŒããšåããããæãã©ããããããC ++ãæã¡è² ãããªãããä»ã®æ¹æ³ã§æéãæœ°ããŸã
第äºã«ãæ¬è³ªäž»çŸ©è
ã¯ãã€ãã£ãã¡ãœãããšåãããã«ã¯æ©èœããŸããã JNIã§éåžžã¢ãŒãã§äœæ¥ããŠãããJVMãåžžã«ã»ãŒããã€ã³ãã«ããŒã«ããã¯ã§ããå Žåãçµã¿èŸŒã¿é¢æ°ã®å Žåãããã¯æ©èœããŸããã èŽåœçãªäœããå£ããªãããã«æ±ãããå¿
èŠããããŸãã
ãããŠç¬¬äžã«ãOpenJDKã®ãã®éšåã«æ®éã®äººãé£çµ¡ããã®ã¯ããŸãå¿«é©ã§ã¯ãªããšããçãããããŸãã ããã«ããã³ãŒãã®å€§éšåã¯æ·±å»ãªãœãŒãµãªãŒã§æ§æãããŠãããããã§åããªããªãå¯èœæ§ããããŸãã
.NETã¯ã©ãã§ããïŒ
ããã€ãã®ã·ã§ãã¯ã¯ããããŒã®ã¢ãããŒãããŸã£ããç°ãªãããšã§ããã ã¢ã»ã³ãã©ããŸã£ããã©ããããªããããããŸããããCïŒããçŽæ¥ãã€ãã£ãã³ãŒããå®è¡ããŸãïŒ
ãã®ã¢ã€ãã¢ã¯ã2005å¹Žã«æžãæ»ãããäŸã«ãã£ãŠèšå®ãããŸããã æ®å¿µãªããããªã³ã¯ã³ãŒãã¯æ©èœããŸãããDEPã¯ããã«ãããæã¡è² ããããã§ãã kernel32.dll
ããã¬ããŒãžããã©ãã°ããŠå°ã倿Žããå¿
èŠããããŸããMemoryProtection
ã VirtualAllocEx
ãšãå¿
èŠãªãã©ã°AllocationType
ãšMemoryProtection
ãŸãã ããã¯ãC ++ã®äŸã§äœ¿çšããããªãã¯ãšãŸã£ããåãã§ãã
äŸãç°¡åã«ããããã«ãLifeãUniverseãEverything Elseã®æãéèŠãªè³ªåã«å¯Ÿããçããè¿ãã¡ãœããããããšããŸãã
using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; class Program { [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect); [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000, Decommit = 0x4000, Release = 0x8000, Reset = 0x80000, Physical = 0x400000, TopDown = 0x100000, WriteWatch = 0x200000, LargePages = 0x20000000 } [Flags] public enum MemoryProtection { Execute = 0x10, ExecuteRead = 0x20, ExecuteReadWrite = 0x40, ExecuteWriteCopy = 0x80, NoAccess = 0x01, ReadOnly = 0x02, ReadWrite = 0x04, WriteCopy = 0x08, GuardModifierflag = 0x100, NoCacheModifierflag = 0x200, WriteCombineModifierflag = 0x400 } private delegate int IntReturner(); private static void Main() { List<byte> bodyBuilder = new List<byte>(); bodyBuilder.Add(0xb8); bodyBuilder.AddRange(BitConverter.GetBytes(42)); bodyBuilder.Add(0xc3); byte[] body = bodyBuilder.ToArray(); IntPtr buf = VirtualAllocEx(Process.GetCurrentProcess().Handle, (IntPtr) 0, Convert.ToUInt32(body.Length), AllocationType.Commit, MemoryProtection.ExecuteReadWrite); Marshal.Copy(body, 0, buf, body.Length); IntReturner ptr = (IntReturner) Marshal.GetDelegateForFunctionPointer(buf, typeof(IntReturner)); Console.WriteLine(ptr()); Console.ReadKey(); } }
ãã©ã¡ãŒã¿ã䜿çšããããã¹ããŒããªãµã³ãã«ãçªç¶å¿
èŠã«ãªã£ãå Žåã Marshal
ã¯AllocHGlobal
ã䜿çšããŠã¢ã³ãããŒãžã¡ã¢ãªãAllocHGlobal
ã AllocHGlobal
ãã¯ãªãŒã³FreeHGlobal
ããåããããã¯FreeHGlobal
ã¡ãœããã䜿çšã§ããŸãã
ãã®ãããªè¶
倧åœã䜿çšãããšãå®éã®ã²ãŒã ãäœæã§ããŸããããšãã°ã ã¯ã©ã¹ã®ã¡ãœããã眮ãæããŸã ã ãã®èšäºãå
¬éããåã«ãGitHubã§å€æ°ã®ãããžã§ã¯ããèŠãŠããŸããããæ®å¿µãªããããããã®ããã¯ã¯C ++ãå®å
šã§ãªãããããŠæãæ²ããããšã«éåžžã«èšå€§ãªã³ãŒããªãã§ã¯ã§ããŸããã§ããã ãããã£ãŠãããã§ã¯ãã¹ãŠã説æããã®ã§ã¯ãªãã.NETã®ãããã³ã°ã«é¢ããå¥ã®èšäºã«èšèŒããŸãã
JVMã³ã³ãã€ã©ã€ã³ã¿ãŒãã§ã€ã¹
è³ãæ£ããæ¹åã«åããããšã§ãJavaã§ãåæ§ã®æ¹æ³ã§åé¡ã解決ã§ããããšãæããã«ãªããŸãã å®éãJava 9ã¯JEP 243ïŒJava-Level JVM Compiler Interfaceãå®è£
ããŠããŸãã
ãã®æ©èœã®éçºè
ã¯ãJITã³ã³ãã€ã©ãæ·±å»ã§ããããšãçè§£ããŠããŸãã ããããš åªããç¡æã®IDEãªã©ãJavaãšã³ã·ã¹ãã ã®ãã¹ãŠã®å¯èœãªæ©èœã䜿çšããŠãåå¥ã«éçºãããšãããœãããŠã§ã¢ã ãããã®æ©èœã®ãã¹ãŠãOpenJDKå
ã§äœ¿çšã§ããããã§ã¯ãããŸãããéåžžããã®ã³ãŒããIDEã§éããšããã¹ãŠãèµ€ããªãããšã©ãŒãšããŠ10åäžç·ãåŒãããŸãã ããŸããŸãªå
éšã¡ã«ããºã ãžã®çŽæ¥ã¢ã¯ã»ã¹ãå¿
èŠãšãããµãã·ã¹ãã ã®ã¢ããªã·ãã¯ã¢ãŒããã¯ãã£ã«ã¯ããçšåºŠã®æ£åœæ§ããããŸãïŒããšãã°ãããã«ã¯ãã€ãã³ãŒãã€ã³ã¿ãŒããªã¿ãŒãŸãã¯ã¬ããŒãžã³ã¬ã¯ã¿ãŒãå¿
èŠã§ãïŒ-ããã¯ã³ã³ãã€ã©ãŒã«ã¯é¢ä¿ãããŸããã
ãããã£ãŠãã³ã³ãã€ã©ãåå¥ã®ãšã³ãã£ãã£ã«åé¢ãããšããèãæ¹ã æ¥ç¶ã¯ãã³ãã³ãã©ã€ã³ã«å«ãŸãããã©ã°ã€ã³ã®åœ¢åŒã§ã䟿å©ã«è¡ãå¿
èŠããããŸãã ããã§ãJVMCIãçãŸããŸããã
ã€ãŸããæãã·ã³ãã«ãªã€ã³ã¿ãŒãã§ã€ã¹ããããŸãã
interface JVMCICompiler { byte[] compileMethod(byte[] bytecode); }
Javaãã€ãã³ãŒããå
¥ãããã€ãã£ãã³ãŒããåºãŠããŸãã CïŒã§äžã«ãã£ããã®ãšéåžžã«ãã䌌ãŠããŸãã ç§ãã¡ã«ãšã£ãŠãããã¯ããã€ãã®ç¹ã§ããã«åªããŠããŸãããã®ãããªäœ¿çšã¯æ±ãå¯äœçšã§ã¯ãªããæãåºæ¬çãªäœ¿çšãã¿ãŒã³ã ããã§ãã
å®éã«ã¯ããã€ãã³ãŒãã ãã§ã¯ååã§ã¯ãããŸããã ããã¯ããã£ãŒã«ãã远å ãããCompilationRequest
ã§ãã
interface JVMCICompiler { void compileMethod(CompilationRequest request); } interface CompilationRequest { JavaMethod getMethod(); } interface JavaMethod { byte[] getCode(); int getMaxLocals(); int getMaxStackSize(); ProfilingInfo getProfilingInfo(); ... }
ã©ãã ãé·ãéãçãéããã€ãã³ãŒããã³ã³ãã€ã«ããã®ã§ã HotSpot.installCode(...);
ã䜿çšããŠå®å
šã«ã€ã³ã¹ããŒã«ã§ããŸãHotSpot.installCode(...);
ç¹ã«ããã®ã¢ãããŒãã¯ãçµã¿èŸŒã¿é¢æ°ã®åæåé¡-OpenJDKãåæ§ç¯ããå¿
èŠæ§ã解決ã§ããŸãã
ããã§ã®åé¡ç¹ã¯ãJVMCIå®è£
ã®äœæãéåžžã«é«éã§ç°¡åãªã¿ã¹ã¯ã§ã¯ãªãããšã§ãã ãã®æ©èœã«é¢ããããã¥ã¡ã³ãã¯ã»ãšãã©ãããŸããã å¯äžã®å
æ¬çãªããã¥ã¡ã³ãã¯OpenJDK C ++ã³ãŒãã§ããããã¯ç§ã¯æ¬åœã«èªã¿ãããããŸããã
ããããããã§ã¯ãã¹ãŠãçãŸããŠããŸãã
ã°ã©ãŒã«ãšããªã¥ã
Oracle Labsã®æããŠæãããã»ã©ãŒã§ã¯ãOpenJDKãè¿ãå°æ¥ã«æ¡åŒµãã人ã®ããã«ç¶æ³ãå€ããããã€ãã®ã¯ãŒã«ãªããŒã«ãéçºãããŠããŸãã ãããã®ãããžã§ã¯ãã¯ãäžè¬åGraalã®äžã«çµ±åããã GitHubã®ãã®ãªããžããªã«ãããŸã ã
å«ãïŒ
- Graal -Javaã§èšè¿°ãããHotSpot JVMãšçµ±åããæé©åã³ã³ãã€ã©
- Truffle -Graalãã¡ã€ã³ã³ã³ãã€ã©ãšããŠäœ¿çšããèšèªãšããŒã«ãäœæããããã®ãã¬ãŒã ã¯ãŒã¯
- Substrate VM -Javaã¢ããªã±ãŒã·ã§ã³ã®äºåïŒAOTïŒã³ã³ãã€ã«ãå®è¡ããå®è¡å¯èœãã¡ã€ã«ã«å€æã§ãããã¬ãŒã ã¯ãŒã¯
è峿·±ãããšã«ãGraalãšTruffleã¯JVMCIã®å®è£
ãæäŸããŸãã ãããŠããã®ãµããŒãã¯ãã§ã«OpenJDK 9ã«ãããŸã-å¿
èŠãªãã©ã°ãæå¹ã«ããã ãã§ãã ãã¡ããããããã®ãã©ã°ãæ¥ç¶ããŠããGraalèªäœãåæ§ç¯ããããšããç§ãã¡ãæãããšã¯ã§ããŸããããéçºè
ããã®åé¡ã«ã©ãã»ã©çå£ã«åãçµãã ãã瀺ããŠããŸãã ããã¯ãã¹ãŠããã§ã«ãã¹ããããŠãããå
¬åŒæ©èœã«ãªãã®ã«ååãªã»ã©æçããŠããããšã瀺ããŠããŸãã
Graalã®ä»çµã¿ã«ã€ããŠéåžžã«è¯ããš ã Chris Seatonæ°ã¯è¿°ã¹ãŠããŸãã ãšããã§ããã®èšäºã¯Joker 2017ã§ã®ã¹ããŒãã«åºã¥ããŠæžãããŠããŸãã
次ã«ãããããã¹ãŠãããŸãæ©èœããå®éã«é©çšå¯èœã§ããããšãã質åã«ç§»ããŸãã åããžã§ãŒã«ãŒã§ãã¯ãªã¹ãã£ã³ã»ã¿ãªã³ãžã£ãŒã¯ ããã€ãã¿ãŒã®ããªãã®éšåããã§ã«Graalã«ç¿»èš³ãããŠãããšè©±ã ãèšã£ãã ã³ã³ãã€ã©ãšããŠäœ¿çšããããšã¯å®çšçã§ããã ãã§ãªããæ¢åã®ã³ãŒãã®ããã©ãŒãã³ã¹ã10ïŒ
以äžåäžãããŸããã
ããã«ã JEP 317ïŒExperimental Java-Based JIT Compilerããã ãããã¯Java 10ã®äžéšã«ãªãå¯èœæ§ããããŸãã
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãGraalãç®çã«ã©ã®ããã«äœ¿çšã§ãããã瀺ãå°ããªåå©äŸãäœæããããšèããŸããã æ®å¿µãªããããã®äŸã¯ãŸã æžãããŠãããé·ãéæžãããŠããããã§ãã ããã¯å¥ã®èšäºã®ãããã¯ã§ãã
ããã«æ¬ ããŠãããã®
VMStructs ã Java Native Runtime ïŒãã®å Žåã¯JNR-x86asm ïŒã Project Panamaå
šäœã¯ã äžåœã«èæ
®ãããŠããŸããã 4æã ã¢ãã³ã®ã³ã¬ããŒãã®åŸãã¹ãã³ãªããäœæããŠãããã®ãããã¯ãæããã«ããå¿
èŠããããŸãã
ãããã«
ãã®èšäºã§ã¯ããã€ãã£ãã³ãŒããJavaããçŽæ¥å®è¡ããæ¹æ³ã瀺ããŸããã
ããã¯ã·ãªãŒãºã®æåã®èšäºã«ãããŸããã æ¬¡ã®ã¹ãããã¯äœã§ããïŒ
æåã«ãã°ã©ãŒã«ãçè§£ããŠããã¯ãªã¹ãã£ã³ã»ã¿ãªã³ãžã£ãŒãšã®ã€ã³ã¿ãã¥ãŒãè¡ãå¿
èŠããããŸãã ã€ã³ã¿ãã¥ãŒã¯è¿ãå°æ¥ã«Habréã§å
¬éãããŸãã
ã¡ãªã¿ã«ã圌ã¯ããã·ãã«ã¹ã¯ã®JBreak 2018ã«æ°ããã¬ããŒããGraalïŒå®éã®çæŽ»ã§æ°ããJVM JITã³ã³ãã€ã©ã䜿çšããæ¹æ³ããæã£ãŠæ¥ãŠããŸãããã®ã¬ããŒãã¯äŸ¡å€ããããŸãã
ãã®ããŒãã«é¢ãã以äžã®èšäºã§ã¯ãGraalãšTruffleã®ã¢ãŒããã¯ãã£ãšæ§æãããã«æ·±ãæãäžããç°¡åãªå€æŽãå ããŠè¿
éãªå¹æãå®çŸããæ¹æ³ã瀺ãå¿
èŠããããŸãã
ããã«ãGraalã®ãã¶ã€ã³ã«åœ±é¿ãäžãããå€ããŠã倱ãããŠããªããŠãŒãã£ãªãã£ãšçŸä»£ã®çŽ æãçµã³ä»ããŠã¿ãããšãã§ããŸãã ããšãã°ã Habréã§ãã®ãããªèšäºïŒæèäŸåãã¬ãŒã¹ã®ã€ã³ã©ã€ã³åïŒããã§ã«å
¬éããŠããŸã ã é¢é£ããéçºã§å€§éã®è³æãèç©ãããŠããŸããããšãã°ãçŸåšã®Graaléçºè
ã§ããDoug Simonã¯ã以åMaxine VMãæ±ã£ãŠããŸããããããã«ã€ããŠã¯éåžžã«å€ãã®åºçç©ããããŸãã