浅谈android系统java调用C++函数传参过程
16lz
2021-01-23
读了《深入理解android》卷一,发现了一点小问题,层层查看源码查资料,浅谈下此文。
//源码目录 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java /** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }-------------------------------------------------------------------------------//源码目录 dalvik/vm/native/dalvik_system_Zygote.cpp/* native public static int forkSystemServer(int uid, int gid, * int[] gids, int debugFlags, long permittedCapabilities, * long effectiveCapabilities); */static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult){ pid_t pid; pid = forkAndSpecializeCommon(args, true); /* The zygote process checks whether the child process has died or not. */ if (pid > 0) { int status; LOGI("System server process %d has been created", pid); gDvm.systemServerPid = pid; /* There is a slight window that the system server process has crashed * but it went unnoticed because we haven't published its pid yet. So * we recheck here just to make sure that all is well. */ if (waitpid(pid, &status, WNOHANG) == pid) { LOGE("System server process %d has died. Restarting Zygote!", pid); kill(getpid(), SIGKILL); } } RETURN_INT(pid);}//源码目录 dalvik/vm/native/dalvik_system_Zygote.cpp/* * Utility routine to fork zygote and specialize the child process. */static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer){ pid_t pid; uid_t uid = (uid_t) args[0]; gid_t gid = (gid_t) args[1]; ArrayObject* gids = (ArrayObject *)args[2]; u4 debugFlags = args[3]; ArrayObject *rlimits = (ArrayObject *)args[4]; int64_t permittedCapabilities, effectiveCapabilities; //被调用函数自行转换参数 if (isSystemServer) { /* * Don't use GET_ARG_LONG here for now. gcc is generating code * that uses register d8 as a temporary, and that's coming out * scrambled in the child process. b/3138621 */ //permittedCapabilities = GET_ARG_LONG(args, 5); //effectiveCapabilities = GET_ARG_LONG(args, 7); permittedCapabilities = args[5] | (int64_t) args[6] << 32; effectiveCapabilities = args[7] | (int64_t) args[8] << 32; } else { permittedCapabilities = effectiveCapabilities = 0; } if (!gDvm.zygote) { dvmThrowIllegalStateException( "VM instance not started with -Xzygote"); return -1; } if (!dvmGcPreZygoteFork()) { LOGE("pre-fork heap failed"); dvmAbort(); } setSignalHandler(); dvmDumpLoaderStats("zygote"); pid = fork(); ...---------------------------------------------------------------------------------
forksystemserver参数不一致了呀,发现没有?原因何在?
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * This uses the FFI (Foreign Function Interface) library to abstract away * the system-dependent stuff. The FFI code is slower than a custom * assembly version, but has the distinct advantage of having been * written already for several platforms. */#include "Dalvik.h"#include "ffi.h"/* * Convert a signature type character to an FFI type. */static ffi_type* getFfiType(char sigType){ switch (sigType) { case 'V': return &ffi_type_void; case 'Z': return &ffi_type_uint8; case 'B': return &ffi_type_sint8; case 'C': return &ffi_type_uint16; case 'S': return &ffi_type_sint16; case 'I': return &ffi_type_sint32; case 'F': return &ffi_type_float; case 'J': return &ffi_type_sint64; case 'D': return &ffi_type_double; case '[': case 'L': return &ffi_type_pointer; default: LOGE("bad ffitype 0x%02x", sigType); dvmAbort(); return NULL; }}/* * Call "func" with the specified arguments. * * The second argument to JNI native functions is either the object (the * "this" pointer) or, for static functions, a pointer to the class object. * The Dalvik instructions will push "this" into argv[0], but it's up to * us to insert the class object. * * Because there is no such thing in as a null "this" pointer, we use * the non-NULL state of "clazz" to determine whether or not it's static. * * For maximum efficiency we should compute the CIF once and save it with * the method. However, this requires storing the data with every native * method. Since the goal is to have custom assembly versions of this * on the platforms where performance matters, I'm recomputing the CIF on * every call. */void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc, const u4* argv, const char* shorty, void* func, JValue* pReturn){ const int kMaxArgs = argc+2; /* +1 for env, maybe +1 for clazz*/ ffi_cif cif; ffi_type* types[kMaxArgs]; void* values[kMaxArgs]; ffi_type* retType; char sigByte; int srcArg, dstArg; types[0] = &ffi_type_pointer; values[0] = &pEnv; types[1] = &ffi_type_pointer; if (clazz != NULL) { values[1] = &clazz; srcArg = 0; } else { values[1] = (void*) argv++; srcArg = 1; } dstArg = 2; /* * Scan the types out of the short signature. Use them to fill out the * "types" array. Store the start address of the argument in "values". */ retType = getFfiType(*shorty); while ((sigByte = *++shorty) != '\0') { types[dstArg] = getFfiType(sigByte); values[dstArg++] = (void*) argv++; if (sigByte == 'D' || sigByte == 'J') argv++; } /* * Prep the CIF (Call InterFace object). */ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, dstArg, retType, types) != FFI_OK) { LOGE("ffi_prep_cif failed"); dvmAbort(); } ffi_call(&cif, FFI_FN(func), pReturn, values);}
在dalvik虚拟机执行native方法有两种,DalvikNativeFunc和DalvikBridgeFunc,头一种方法有虚拟机直接调用,用指针传递参数,很简洁,比如const u4*,需要时在被调用方法里自行转换参数,并不需要方法签名的帮助来转换参数,方法签名只用于标示重载函数,这些函数可以理解成虚拟机的一部分,设计时针对不同平台进行编码,会调用不同平台的系统函数。第二种jni调用了,从源码可知在调用时会加入env 和clazz参数 ,并根据方法签名转换参数。需要说明的是在jni调用方面 ffi方式一般用于未知平台。像arm和x86平台都用汇编实现了。
更多相关文章
- Android Studio sdk tools文件夹下文件缺失问题以及解决方法
- Android -- 加载大图片的方法
- [Android] Handler源码解析 (Java层)
- Android开发之fedora13下编译Android源码
- Xamarin 中开发Android实现全屏或者不显示标题栏的方法-宋兴柱
- Android 字体加粗的两种方法
- Android×××方法详解
- 【解决方法】ADT在线安装