プラットフォームを抽象化したC API(Java編)

C言語への感謝の正拳突き 今日は19日目です！

もうほんとC言語に関する実用的なネタが無くてですね、
マクロネタを書くとMordernなC++に誘導せざるをえないし、
C言語のAPIネタでお茶を濁そうかと思います。

# プラットフォーム抽象化レイヤ
何日か前の正拳突きでも紹介しました、プラットフォーム抽象化レイヤみたいのは、
マルチプラットフォーム対応したライブラリであったり、VMでは標準でさぽーとしているのですが、
今回はその中でも最もメジャーなJava(OracleJDK)がどんな感じかみてみようと思います。

抽象化レイヤの特徴として、たとえば
(1) OS(A)固有のオプションを操作可能な複雑なAPI
(2) OS(B)の単純なことしかできないAPI

これを抽象化しようとすると、大部分において、OS(B)の単純なAPIをベースにして定義することになり、
OS(A)固有のオプションというのは犠牲になることが多いです。

例をあげると、ファイルまわりのセキュリティですね。
OracleJDKといいましたが、大部分はOpenJDKと同じなので、まずはOpenJDKを取得してきましょう。

# OpenJDKの取得方法

mercurialのリポジトリが公開されています。
http://hg.openjdk.java.net/

repositoryの説明とかソースコードの取得方法
http://openjdk.java.net/guide/repositories.html

実際の取得コマンド(ubuntu14)

```:
$ hg clone http://hg.openjdk.java.net/jdk8u/jdk8u
$ pushd jdk8
$ sh ./get_source.sh 
ERROR: Could not determine Mercurial version of /usr/bin/hg
$ export LANGUAGE=en
$ sh ./get_source.sh 
```

# ディレクトリの構成

```:jdk8u
  hotspot (VMのソースコード C++主体)
    src
      cpu
      os
      os_cpu
      share
        vm
  jdk (JDKのlibraryのソースコード Java, C++, C)
    src
      aix         //このフォルダ分けだけでどのプラットフォームに対応しているのかわかる
      bsd
      linux
      macosx
      share       //Pure Javaなjdkのコード。大部分はここに定義されている
      solaris　　　//歴史的な事情
      windows     //
```

ここまで手順を書いて、、私が調査しようとしていたのは、JVM編ではなくJava編であったことに気づく。。

なので、jdkのソースコードのほうを主体に調べました。
(わたしの進捗がよければ)JVM編では、可能な限りhotspotの中のos抽象化レイヤみたいを見てみようかと思います。


基本的には、調べたいJavaのクラスやAPIをgrepで探して、
srcの下のOSごとに分かれてる中でどんな定義になっているのか調べるだけです。

# JDKのプラットフォーム抽象化レイヤ

JDKのプラットフォーム抽象化レイヤがどういう階層構造になっているのか説明します。

基本的に、JavaのAPIでOSのSystemCallたたきそうなやつは、以下の4階層から構成されています。
Java -> JNI -> C API -> OS SystemCall

JNIの概要や使い方はhishidamaさんが詳しいです。
http://www.ne.jp/asahi/hishidama/home/tech/java/jni.html

前半の(Java -> JNI)までが、プラットフォーム抽象化されたAPIであり、
後半の(C API -> OS SystemCall)がプラットフォームごとに定義されています。

そのため、後半のプラットフォームごとに定義された部分は、そのプラットフォームのライブラリという形態を取っており、
JNIのloadLibraryでプラットフォームごとに定義されたライブラリを呼び出しています。

プラットフォームごとに定義されたライブラリがどこにあるのかというと、jdkの中にはいっていました。

下記は、64bit linux向けのOracleJDKを展開したディレクトリです。

```:jdk1.8.0_60/jre/lib/amd64
jre/lib/amd64$ ls
jli  // javaコマンドのlunchar
libattach.so  // Java_sun_tools_attach_ってのがあるらしい
libavplugin-53.so  //動画再生系？ GStreamerやmpegやtsやvideodecorderとか
libavplugin-54.so
libawt.so          //Abstract Window Toolkit(略してAWT)
libawt_headless.so
libawt_xawt.so
libbci.so          //Java Bytecode Instrumentationらしい。Java_jdk_internal_instrumentation
libdcpr.so         //Java_sun_dc_pr Awt2dLibrariesから参照される謎のライブラリ http://pag-www.gtisc.gatech.edu/chord/examples/jdk/sun/dc/pr/PathStroker.java.html
libdecora_sse.so   //Java_com_sun_scenario_effectにSSE使うためのライブラリ？
libdeploy.so       //Java_com_sun_deploy
libdt_socket.so    //debugやtrace用のsocket?
libfontmanager.so  //Java_sun_font
libfxplugins.so    //VP6 gst flvとか
libglass.so        //Java_com_sun_glass
libgstreamer-lite.so  //gstreamer
libhprof.so        //javaのhprof用
libinstrument.so   //Java_sun_instrument
libj2gss.so        //Java_sun_security_jgss
libj2pcsc.so       //Java_sun_security_smartcardio
libj2pkcs11.so     //Java_sun_security_pkcs11
libjaas_unix.so    //Java_com_sun_security_auth
libjava.so         //Java_langやJava_ioとかいろいろ
libjava_crw_demo.so
libjavafx_font.so  //Java_com_sun_javafx
libjavafx_font_freetype.so
libjavafx_font_pango.so
libjavafx_font_t2k.so
libjavafx_iio.so   // jpeg系らしい
libjawt.so         // awt
libjdwp.so         // Java Debug Wire Protocol
libjfr.so          // Java_oracle_jrockit_jfr
libjfxmedia.so     // C++製 Java_com_sun_media_jfxmedia
libjfxwebkit.so
libjpeg.so         //Java_com_sun_imageio_plugins_jpeg
libjsdt.so         //Java_sun_tracing_dtrace
libjsig.so         //sigXXX系総まとめ
libjsound.so       //Java_com_sun_media_sound
libjsoundalsa.so   //Java_com_sun_media_sound
libkcms.so         //Java_sun_java2d_cmm_kcms
liblcms.so         //Java_sun_java2d_cmm_lcms
libmanagement.so   //Java_sun_management
libmlib_image.so   //mlib
libnet.so          //Java_sun_net Java_java_net
libnio.so          //Java_sun_nio
libnpjp2.so        //C++製 Java_sun_plugin2
libnpt.so          //NPT(Native Platform Toolkit)
libprism_common.so //Java_com_sun_prism
libprism_es2.so    //Java_com_sun_prism_es2
libprism_sw.so     //Java_com_sun_pisces_
libresource.so     //Java_jdk_management_resource
libsaproc.so       //Java_sun_jvm_hotspot_debugger
libsctp.so         //Java_sun_nio_ch_sctp_
libsplashscreen.so //screen制御？
libsunec.so        //Java_sun_security_ec
libt2k.so          //Java_sun_font_T2KFontScaler
libunpack.so       //Java_com_sun_java_util_jar_pack
libverify.so       //class verifier
libzip.so          //Java_java_util_zip
server/libjvm.so   //JVM_XXXってprefix

```

こんな感じですね。
net系はたぶんlibnet.soだろうし、ファイルIO系はlibnio.soだろうし、
java.lang系はどこにはいっているのだろう。。libjava.soか！？

実際にobjdumpする以外に、jdk8u/jdk/make/mapfileにexportされているシンボルが定義されていました。
こちらのほうが整理されていて読みやすいですね。
http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/6ea3aea950d1/make/mapfiles

ちなみにJavaVM本体は、上記serverディレクトリの中に入っているlibjvm.soです。

# 具体例

たとえば、java.io.File.exists()を探してみようと思います。
jdkの下で適当にgrepしてみる。。


```java:jdk/src/share/classes/java/io/File.java
public boolean exists() {
  SecurityManager security = System.getSecurityManager();
  if (security != null) {
    security.checkRead(path);
  }
  if (isInvalid()) {
    return false;
  }
  return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
}

```

getBooleanAttributes()の結果のbitに、BA_EXISTSが立ってればexist判定みたいなコードですね。
とりあえずfs.getBooleanAttributesでも探してみるか。


```java:jdk/src/share/classes/java/io/FileSystem.java:
    /* -- Attribute accessors -- */

    /* Constants for simple boolean attributes */
    @Native public static final int BA_EXISTS    = 0x01;
    @Native public static final int BA_REGULAR   = 0x02;
    @Native public static final int BA_DIRECTORY = 0x04;
    @Native public static final int BA_HIDDEN    = 0x08;

    /**
     * Return the simple boolean attributes for the file or directory denoted
     * by the given abstract pathname, or zero if it does not exist or some
     * other I/O error occurs.
     */
    public abstract int getBooleanAttributes(File f);

    @Native public static final int ACCESS_READ    = 0x04;
    @Native public static final int ACCESS_WRITE   = 0x02;
    @Native public static final int ACCESS_EXECUTE = 0x01;

```

まだJavaの世界だ。。
上記見てもらえば分かりますが、BooleanAttributesで取得できる属性は4種類しかありません。

```java:jdk/src/solaris/classes/java/io/UnixFileSystem.java
    /* -- Attribute accessors -- */

    public native int getBooleanAttributes0(File f);

    public int getBooleanAttributes(File f) {
        int rv = getBooleanAttributes0(f);
        String name = f.getName();
        boolean hidden = (name.length() > 0) && (name.charAt(0) == '.');
        return rv | (hidden ? BA_HIDDEN : 0);
    }

```

きたー、やっとnativeの世界に降りてきた。
そもそもsolarisってなんだよ。。歴史的な経緯ですかね。。

ここからnativeの世界(JNI)に降りていきます。

```C:jdk/src/solaris/native/java/io/UnixFileSystem_md.c

/* -- Attribute accessors -- */


static jboolean
statMode(const char *path, int *mode)
{
    struct stat64 sb;
    if (stat64(path, &sb) == 0) {
        *mode = sb.st_mode;
        return JNI_TRUE;
    }
    return JNI_FALSE;
}


JNIEXPORT jint JNICALL
Java_java_io_UnixFileSystem_getBooleanAttributes0(JNIEnv *env, jobject this,
                                                  jobject file)
{
    jint rv = 0;

    WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
        int mode;
        if (statMode(path, &mode)) {
            int fmt = mode & S_IFMT;
            rv = (jint) (java_io_FileSystem_BA_EXISTS
                  | ((fmt == S_IFREG) ? java_io_FileSystem_BA_REGULAR : 0)
                  | ((fmt == S_IFDIR) ? java_io_FileSystem_BA_DIRECTORY : 0));
        }
    } END_PLATFORM_STRING(env, path);
    return rv;
}
```

まずはUNIX版のコード、普通にstatして確認するコードですね。

man fstat64
http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=fstat64

```C:jdk/src/windows/native/java/io/WinNTFileSystem_md.c
JNIEXPORT jint JNICALL
Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
                                                  jobject file)
{
    jint rv = 0;
    jint pathlen;

    WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
    if (pathbuf == NULL)
        return rv;
    if (!isReservedDeviceNameW(pathbuf)) {
        DWORD a = getFinalAttributes(pathbuf);
        if (a != INVALID_FILE_ATTRIBUTES) {
            rv = (java_io_FileSystem_BA_EXISTS
                | ((a & FILE_ATTRIBUTE_DIRECTORY)
                    ? java_io_FileSystem_BA_DIRECTORY
                    : java_io_FileSystem_BA_REGULAR)
                | ((a & FILE_ATTRIBUTE_HIDDEN)
                    ? java_io_FileSystem_BA_HIDDEN : 0));
        }
    }
    free(pathbuf);
    return rv;
}
```

お次はWindowsのコードです。
getFinalAttributes()で確認するみたいですね。

getFinalAttributes()のMSDN
https://msdn.microsoft.com/ja-jp/library/cc429313.aspx


一応、ライブラリをobjdumpしてシンボルの有無を確認してみたら、
libjava.soで定義されていました。

java.ioやjava.langの基本的なのはlibjava.soで定義されてるのかもしれませんね。
ご参考までに、libjava.soのシンボルをJava_javaでgrepしてみました。


```C:libjava.so
Java_java_io_UnixFileSystem_getLastModifiedTime
Java_java_lang_UNIXProcess_forkAndExec
Java_java_io_UnixFileSystem_delete0
Java_java_lang_Throwable_fillInStackTrace
Java_java_io_FileOutputStream_writeBytes
Java_java_lang_StrictMath_hypot
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2
Java_java_lang_ClassLoader_00024NativeLibrary_unload
Java_java_lang_SecurityManager_currentClassLoader0
Java_java_util_TimeZone_getSystemTimeZoneID
Java_java_io_UnixFileSystem_list
Java_java_io_FileInputStream_open0
Java_java_lang_reflect_Array_setByte
Java_java_lang_StrictMath_log1p
Java_java_io_RandomAccessFile_setLength
Java_java_nio_Bits_copyToIntArray
Java_java_lang_Runtime_traceInstructions
Java_java_lang_reflect_Array_getByte
Java_java_io_FileOutputStream_write
Java_java_io_FileInputStream_initIDs
Java_java_lang_StrictMath_expm1
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2
Java_java_lang_ClassLoader_findBuiltinLib
Java_java_lang_reflect_Executable_getTypeAnnotationBytes0
Java_java_lang_Package_getSystemPackages0
Java_java_lang_System_initProperties
Java_java_lang_Runtime_availableProcessors
Java_java_lang_ClassLoader_defineClass1
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8
Java_java_lang_reflect_Array_getInt
Java_java_lang_Runtime_totalMemory
Java_java_lang_Compiler_registerNatives
Java_java_io_ObjectOutputStream_floatsToBytes
Java_java_lang_StrictMath_asin
Java_java_io_ObjectInputStream_bytesToDoubles
Java_java_lang_reflect_Array_setChar
Java_java_lang_reflect_Array_set
Java_java_lang_StrictMath_exp
Java_java_security_AccessController_getStackAccessControlContext
Java_java_io_RandomAccessFile_length
Java_java_io_Console_istty
Java_java_lang_Package_getSystemPackage0
Java_java_lang_SecurityManager_classDepth
Java_java_lang_Object_registerNatives
Java_java_lang_reflect_Array_setShort
Java_java_io_UnixFileSystem_initIDs
Java_java_lang_UNIXProcess_waitForProcessExit
Java_java_lang_StrictMath_sinh
Java_java_io_RandomAccessFile_close0
Java_java_io_UnixFileSystem_checkAccess
Java_java_lang_Double_longBitsToDouble
Java_java_lang_reflect_Array_get
Java_java_lang_StrictMath_log
Java_java_security_AccessController_getStackAccessControlContext
Java_java_io_RandomAccessFile_length
Java_java_io_Console_istty
Java_java_lang_Package_getSystemPackage0
Java_java_lang_SecurityManager_classDepth
Java_java_lang_Object_registerNatives
Java_java_lang_reflect_Array_setShort
Java_java_io_UnixFileSystem_initIDs
Java_java_lang_UNIXProcess_waitForProcessExit
Java_java_lang_StrictMath_sinh
Java_java_io_RandomAccessFile_close0
Java_java_io_UnixFileSystem_checkAccess
Java_java_lang_Double_longBitsToDouble
Java_java_lang_reflect_Array_get
Java_java_lang_StrictMath_log
Java_java_nio_Bits_copyFromShortArray
Java_java_io_Console_encoding
Java_java_io_RandomAccessFile_write0
Java_java_lang_Runtime_traceMethodCalls
Java_java_io_RandomAccessFile_read0
Java_java_security_AccessController_getInheritedAccessControlContext
Java_java_nio_Bits_copyToShortArray
Java_java_io_FileOutputStream_close0
Java_java_util_prefs_FileSystemPreferences_lockFile0
Java_java_lang_reflect_Proxy_defineClass0
Java_java_lang_Throwable_getStackTraceElement
Java_java_lang_UNIXProcess_init
Java_java_lang_Class_isInstance
Java_java_lang_System_registerNatives
Java_java_lang_SecurityManager_currentLoadedClass0
Java_java_lang_String_intern
Java_java_lang_reflect_Array_getFloat
Java_java_lang_Runtime_freeMemory
Java_java_lang_Runtime_gc
Java_java_io_FileInputStream_readBytes
Java_java_lang_reflect_Array_setFloat
Java_java_lang_Double_doubleToRawLongBits
Java_java_lang_Class_isAssignableFrom
Java_java_lang_UNIXProcess_destroyProcess
Java_java_lang_StrictMath_log10
Java_java_lang_StrictMath_sqrt
Java_java_lang_reflect_Array_getLong
Java_java_io_RandomAccessFile_readBytes
Java_java_io_FileOutputStream_initIDs
Java_java_io_RandomAccessFile_seek0
Java_java_lang_reflect_Array_setBoolean
Java_java_io_ObjectStreamClass_hasStaticInitializer
Java_java_io_UnixFileSystem_createFileExclusively
Java_java_util_TimeZone_getSystemGMTOffsetID
Java_java_lang_StrictMath_cos
Java_java_io_UnixFileSystem_canonicalize0
Java_java_lang_StrictMath_cosh
Java_java_lang_StrictMath_cbrt
Java_java_lang_ClassLoader_defineClass0
Java_java_io_FileInputStream_skip
Java_java_lang_ClassLoader_findLoadedClass0
Java_java_io_UnixFileSystem_getBooleanAttributes0
Java_java_lang_Runtime_runFinalization0
Java_java_lang_System_identityHashCode
Java_java_lang_StrictMath_pow
Java_java_io_RandomAccessFile_open0
Java_java_io_RandomAccessFile_initIDs
Java_java_util_prefs_FileSystemPreferences_chmod
Java_java_lang_StrictMath_tanh
Java_java_lang_reflect_Array_getDouble
Java_java_lang_Runtime_maxMemory
Java_java_lang_Shutdown_runAllFinalizers
Java_java_lang_reflect_Executable_getParameters0
Java_java_io_UnixFileSystem_rename0
Java_java_nio_Bits_copyFromIntArray
Java_java_lang_SecurityManager_getClassContext
Java_java_lang_System_mapLibraryName
Java_java_io_FileOutputStream_open0
Java_java_io_RandomAccessFile_writeBytes
Java_java_lang_StrictMath_atan2
Java_java_io_ObjectOutputStream_doublesToBytes
Java_java_util_prefs_FileSystemPreferences_unlockFile0
Java_java_io_UnixFileSystem_createDirectory
Java_java_io_ObjectStreamClass_initNative
Java_java_lang_reflect_Array_setInt
Java_java_lang_ClassLoader_registerNatives
Java_java_lang_Thread_registerNatives
Java_java_lang_reflect_Field_getTypeAnnotationBytes0
Java_java_lang_ClassLoader_00024NativeLibrary_find
Java_java_lang_Shutdown_halt0
Java_java_lang_System_setErr0
Java_java_lang_reflect_Array_getShort
Java_java_lang_StrictMath_tan
Java_java_lang_reflect_Array_getBoolean
Java_java_io_FileInputStream_close0
Java_java_lang_reflect_Array_newArray
Java_java_lang_StrictMath_sin
Java_java_lang_System_setIn0
Java_java_lang_reflect_Array_setLong
Java_java_lang_Throwable_getStackTraceDepth
Java_java_io_FileInputStream_read0
Java_java_io_RandomAccessFile_getFilePointer
Java_java_lang_SecurityManager_classLoaderDepth0
Java_java_io_ObjectInputStream_bytesToFloats
Java_java_lang_ClassLoader_resolveClass0
Java_java_io_UnixFileSystem_setReadOnly
Java_java_lang_reflect_Array_getChar
Java_java_io_FileDescriptor_sync
Java_java_lang_reflect_Array_getLength
Java_java_lang_reflect_Array_multiNewArray
Java_java_io_FileDescriptor_initIDs
Java_java_io_FileInputStream_available
Java_java_io_Console_echo
Java_java_lang_Object_getClass
Java_java_io_UnixFileSystem_getSpace
Java_java_nio_Bits_copyToLongArray
Java_java_io_UnixFileSystem_getLength
Java_java_nio_Bits_copyFromLongArray
Java_java_lang_Class_forName0
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2
Java_java_io_UnixFileSystem_setPermission
Java_java_lang_reflect_Array_setDouble
Java_java_lang_StrictMath_acos
Java_java_lang_StrictMath_atan
Java_java_lang_Class_registerNatives
Java_java_io_UnixFileSystem_setLastModifiedTime
Java_java_lang_Float_intBitsToFloat
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2
Java_java_lang_Class_getPrimitiveClass
Java_java_lang_ClassLoader_00024NativeLibrary_load
Java_java_lang_StrictMath_IEEEremainder
Java_java_util_logging_FileHandler_isSetUID
Java_java_lang_Float_floatToRawIntBits
Java_java_lang_ProcessEnvironment_environ
Java_java_lang_ClassLoader_defineClass2
Java_java_lang_System_setOut0
Java_java_lang_ClassLoader_findBootstrapClass

```

Java_java_security系のシンボルの長さはバグってるんじゃないかって疑いたくなりますね。。

# 具体例2

具体例として、もう1つくらい java.nio.file.attribute.AclFileAttributeView.setAcl(List<AclEntry> acl)

javadoc Interface AclFileAttributeView
https://docs.oracle.com/javase/8/docs/api/java/nio/file/attribute/AclFileAttributeView.html

ちょっと飛ばしぎみで見ていくと、AclFileAttributeViewはinterfaceなので、
実装はJavaのソースコードの段階でSolaris版とWindows版に分かれているようでした。


```java:jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java
    @Override
    public void setAcl(List<AclEntry> acl) throws IOException {
        // permission check
        checkAccess(file, false, true);

        // open file (will fail if file is a link and not following links)
        int fd = file.openForAttributeAccess(followLinks);
        try {
            // SECURITY: need to copy list as can change during processing
            acl = new ArrayList<AclEntry>(acl);
            int n = acl.size();

            long address = unsafe.allocateMemory(SIZEOF_ACE_T * n);
            try {
                encode(acl, address);
                facl(fd, ACE_SETACL, n, address);
            } catch (UnixException x) {
                if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
                    throw new FileSystemException(file.getPathForExceptionMessage(),
                        null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
                }
                if (x.errno() == EINVAL && (n < 3))
                    throw new IOException("ACL must contain at least 3 entries");
                x.rethrowAsIOException(file);
            } finally {
                unsafe.freeMemory(address);
            }
        } finally {
            close(fd);
        }
    }

```

setAclのUNIX版、facl(4)を呼び出しているけど、じったいはこれらしい

```C:jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c
JNIEXPORT jint JNICALL
Java_sun_nio_fs_SolarisNativeDispatcher_facl(JNIEnv* env, jclass this, jint fd,
    jint cmd, jint nentries, jlong address)
{
    void* aclbufp = jlong_to_ptr(address);
    int n = -1;

    n = facl((int)fd, (int)cmd, (int)nentries, aclbufp);
    if (n == -1) {
        throwUnixException(env, errno);
    }
    return (jint)n;
}

```

man facl
https://docs.oracle.com/cd/E26502_01/html/E29032/acl-2.html
facl systemcallがあるのはsolarisだけだよな。。
linuxの場合は、、、umask()か？

umask()は、libjava.soが参照しているようだけど、、

```C:jdk/src/solaris/native/sun/nio/fs

BsdNativeDispatcher.c    MacOSXNativeDispatcher.c   UnixCopyFile.c
GnomeFileTypeDetector.c  MagicFileTypeDetector.c    UnixNativeDispatcher.c
LinuxNativeDispatcher.c  SolarisNativeDispatcher.c
LinuxWatchService.c      SolarisWatchService.c

```
同じ階層のLinuxNativeDispatcher.cを参照すると、setxattrを呼び出しているのかなと思ったけれども、
どこでどういう過程で呼び出されるのかまでは探せなかった。
https://linuxjm.osdn.jp/html/LDP_man-pages/man2/setxattr.2.html

動かしてみてstraceで検証できると思いますが、今回はパスしました。

```java:jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java
@Override
    public void setAcl(List<AclEntry> acl) throws IOException {
        checkAccess(file, false, true);

        // SetFileSecurity does not follow links so when following links we
        // need the final target
        String path = WindowsLinkSupport.getFinalPath(file, followLinks);
        WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.create(acl);
        try {
            SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd.address());
        } catch (WindowsException x) {
             x.rethrowAsIOException(file);
        } finally {
            sd.release();
        }
    }

```

実体はSetFileSecurityなのかな。


```C:
JNIEXPORT void JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_SetFileSecurity0(JNIEnv* env, jclass this,
   jlong pathAddress, jint requestedInformation, jlong descAddress)
{
   LPCWSTR lpFileName = jlong_to_ptr(pathAddress);
   PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress);
   DWORD lengthNeeded = 0;

   BOOL res = SetFileSecurityW(lpFileName,
                               (SECURITY_INFORMATION)requestedInformation,
                               pSecurityDescriptor);

   if (res == 0) {
       throwWindowsException(env, GetLastError());
   }
}
```

msdnの説明、SetFileSecurity
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa379577(v=vs.85).aspx

と思ったら、This function is obsolete. Use the SetNamedSecurityInfo function instead.
なんて説明が。。。
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa379579(v=vs.85).aspx

この辺が、冒頭で述べた単純なAPIと、複雑なオプションを持ったAPIの違いなんだと思います。
いざってときはJNIなりJNAで拡張すればいいんでしょう！？


# まとめ

JDKはマルチプラットフォーム対応したライブラリだったんだよ！というのが確認できました。
こうしてコードを追ってみると、JavaNativeInterfaceは、ただJavaからC/C++のメソッドを呼び出すための補助機能なのではなく、Javaのプラットフォーム抽象化レイヤを支える中核機能であることがわかります。

Javaのライブラリ作ってる人たちは大変ですよね、感謝です。

マルチプラットフォーム対応したライブラリを再開発するのはそろそろやめたい、と考えているあなた、jreのライブラリをlinkしてしまえばいいのでは...(震え声)