前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NDK--andfix热修复之art虚拟机

NDK--andfix热修复之art虚拟机

作者头像
aruba
发布2020-07-03 10:03:40
5290
发布2020-07-03 10:03:40
举报
文章被收录于专栏:android技术android技术
so插件化原理,hook技术实现andfix热修复中,只实现了dalvik虚拟机中的热修复,安卓5.0后,谷歌彻底抛弃dalvik虚拟机,改用art虚拟机。
在dalvik虚拟机中,应用启动首先会加载dex成class字节码,然后采用JIT技术,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码(CPU真正识别二进制),虽然转换时会利用缓存技术优化,但还是会造成应用运行速度。
在art虚拟机中,在应用安装时,就通过dex2oat工具把dex文件转换为oat文件,oat文件中同时存放着字节码和机器码,这就造成了art虚拟机下安装应用比较慢,应用运行速度却大大提升了。
上次我们在api19以下的情况,将两个Method对象传给native层进行函数指针替换,今天来做19以上的适配
代码语言:javascript
复制
package com.aruba.andfixapplication;

import android.content.Context;
import android.os.Build;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;

import dalvik.system.DexFile;

/**
 * Created by aruba on 2020/4/30.
 */
public class DexManager {
    private Context mContext;

    private static final DexManager ourInstance = new DexManager();

    public static DexManager getInstance() {
        return ourInstance;
    }

    private DexManager() {
    }

    public void setContext(Context mContext) {
        this.mContext = mContext;
    }

    public void loadDexFile(File file) {
        try {
            DexFile dexFile = DexFile.loadDex(file.getAbsolutePath(),
                    new File(mContext.getCacheDir(), "fix.dex").getAbsolutePath(),
                    Context.MODE_PRIVATE);
            //类名迭代器
            Enumeration<String> entry = dexFile.entries();
            while (entry.hasMoreElements()) {
                String className = entry.nextElement();
                //Class.forName()获取不到,因为没有加载,我们需要手动加载
                Class clazz = dexFile.loadClass(className, mContext.getClassLoader());
                if (clazz != null) {
                    //开始修复
                    fixClass(clazz);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void fixClass(Class clazz) {
        //获取class中的方法
        Method[] methods = clazz.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) {
            //获取注解
            Replace replace = methods[i].getAnnotation(Replace.class);
            if (replace == null) continue;

            //获取注解中需要被修复的方法和类
            String bugClazzStr = replace.clazz();
            String bugMethodStr = replace.method();

            try {
                Class bugClazz = Class.forName(bugClazzStr);
                //错误的方法
                Method bugMethod = bugClazz.getMethod(bugMethodStr, methods[i].getParameterTypes());
                if (Build.VERSION.SDK_INT <= 19) {//18版本以下,dalvik
                    replace(Build.VERSION.SDK_INT, bugMethod, methods[i], clazz);
                } else if (Build.VERSION.SDK_INT == 24) {
                    replaceArt7(bugMethod, methods[i]);
                } else {
                    replaceArt(bugMethod, methods[i]);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

    private native void replace(int sdk, Method wrongMethod, Method rightMethod, Class rightClazz);

    private native void replaceArt(Method wrongMethod, Method rightMethod);

    private native void replaceArt7(Method wrongMethod, Method rightMethod);
}
7.0的方法结构体和其他的不同,并且andfix只支持到7.0

7.0以下art虚拟机的ArtMethod头文件

代码语言:javascript
复制
/*
 *
 * Copyright (c) 2011 The Android Open Source Project
 * Copyright (c) 2015, alipay.com
 *
 * 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.
 */

/**
 *  art_5_1.h
 *
 * @author : sanping.li@alipay.com
 *
 */
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <fcntl.h>
#include <dlfcn.h>

#include <stdint.h>    /* C99 */

typedef unsigned char u1;
typedef unsigned short u2;
typedef unsigned int u4;
typedef signed char s1;
typedef signed short s2;
typedef signed int s4;

namespace art {
    namespace mirror {
        class Object {
        public:
            // The number of vtable entries in java.lang.Object.
            uint32_t klass_;

            uint32_t monitor_;
        };

        class Class : public Object {
        public:
            // Interface method table size. Increasing this value reduces the chance of two interface methods
            // colliding in the interface method table but increases the size of classes that implement
            // (non-marker) interfaces.
            // defining class loader, or NULL for the "bootstrap" system loader
            uint32_t class_loader_;
            // For array classes, the component class object for instanceof/checkcast
            // (for String[][][], this will be String[][]). NULL for non-array classes.
            uint32_t component_type_;
            // DexCache of resolved constant pool entries (will be NULL for classes generated by the
            // runtime such as arrays and primitive classes).
            uint32_t dex_cache_;
            // Short cuts to dex_cache_ member for fast compiled code access.
            uint32_t dex_cache_strings_;
            // static, private, and <init> methods
            uint32_t direct_methods_;
            // instance fields
            //
            // These describe the layout of the contents of an Object.
            // Note that only the fields directly declared by this class are
            // listed in ifields; fields declared by a superclass are listed in
            // the superclass's Class.ifields.
            //
            // All instance fields that refer to objects are guaranteed to be at
            // the beginning of the field list.  num_reference_instance_fields_
            // specifies the number of reference fields.
            uint32_t ifields_;
            // The interface table (iftable_) contains pairs of a interface class and an array of the
            // interface methods. There is one pair per interface supported by this class.  That means one
            // pair for each interface we support directly, indirectly via superclass, or indirectly via a
            // superinterface.  This will be null if neither we nor our superclass implement any interfaces.
            //
            // Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()".
            // Invoke faceObj.blah(), where "blah" is part of the Face interface.  We can't easily use a
            // single vtable.
            //
            // For every interface a concrete class implements, we create an array of the concrete vtable_
            // methods for the methods in the interface.
            uint32_t iftable_;
            // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
            uint32_t name_;
            // Static fields
            uint32_t sfields_;
            // The superclass, or NULL if this is java.lang.Object, an interface or primitive type.
            uint32_t super_class_;
            // If class verify fails, we must return same error on subsequent tries.
            uint32_t verify_error_class_;
            // Virtual methods defined in this class; invoked through vtable.
            uint32_t virtual_methods_;
            // Virtual method table (vtable), for use by "invoke-virtual".  The vtable from the superclass is
            // copied in, and virtual methods from our class either replace those from the super or are
            // appended. For abstract classes, methods may be created in the vtable that aren't in
            // virtual_ methods_ for miranda methods.
            uint32_t vtable_;
            // Access flags; low 16 bits are defined by VM spec.
            uint32_t access_flags_;
            // Total size of the Class instance; used when allocating storage on gc heap.
            // See also object_size_.
            uint32_t class_size_;
            // Tid used to check for recursive <clinit> invocation.
            pid_t clinit_thread_id_;
            // ClassDef index in dex file, -1 if no class definition such as an array.
            // TODO: really 16bits
            int32_t dex_class_def_idx_;
            // Type index in dex file.
            // TODO: really 16bits
            int32_t dex_type_idx_;
            // Number of instance fields that are object refs.
            uint32_t num_reference_instance_fields_;
            // Number of static fields that are object refs,
            uint32_t num_reference_static_fields_;
            // Total object size; used when allocating storage on gc heap.
            // (For interfaces and abstract classes this will be zero.)
            // See also class_size_.
            uint32_t object_size_;
            // Primitive type value, or Primitive::kPrimNot (0); set for generated primitive classes.
            uint32_t primitive_type_;
            // Bitmap of offsets of ifields.
            uint32_t reference_instance_offsets_;
            // Bitmap of offsets of sfields.
            uint32_t reference_static_offsets_;
            // State of class initialization.
            int32_t status_;
            // TODO: ?
            // initiating class loader list
            // NOTE: for classes with low serialNumber, these are unused, and the
            // values are kept in a table in gDvm.
            // InitiatingLoaderList initiating_loader_list_;
            // The following data exist in real class objects.
            // Embedded Imtable, for class object that's not an interface, fixed size.
            // ImTableEntry embedded_imtable_[0];
            // Embedded Vtable, for class object that's not an interface, variable size.
            // VTableEntry embedded_vtable_[0];
            // Static fields, variable size.
            // uint32_t fields_[0];
            // java.lang.Class
            static void *java_lang_Class_;
        };

        class ArtField : public Object {
        public:
            uint32_t declaring_class_;
            int32_t access_flags_;
            int32_t field_dex_idx_;
            int32_t offset_;
        };

        class ArtMethod : public Object {
        public:
            // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
            // The class we are a part of. 适配andfix  不能做到这一改
            uint32_t declaring_class_;


            // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access. dex
            uint32_t dex_cache_resolved_methods_;
            // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
            uint32_t dex_cache_resolved_types_;
            // Access flags; low 16 bits are defined by spec.
            uint32_t access_flags_;
            /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
            // Offset to the CodeItem.
            uint32_t dex_code_item_offset_;
            // Index into method_ids of the dex file associated with this method.
            uint32_t dex_method_index_;
            /* End of dex file fields. */
            // Entry within a dispatch table for this method. For static/direct methods the index is into
            // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
            // ifTable.
            uint32_t method_index_;
            // Fake padding field gets inserted here.
            // Must be the last fields in the method.
            struct PtrSizedFields {
                // Method dispatch from the interpreter invokes this pointer which may cause a bridge into
                // compiled code.java方法   ----》 虚拟机   ----》方法的入口 entry_point_from_interpreter_
                //art  解释模式  机器码
                void *entry_point_from_interpreter_;
                // Pointer to JNI function registered to this method, or a function to resolve the JNI function.
                void *entry_point_from_jni_;
                // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
                // portable compiled code or the interpreter.
//                 机器码模式
                void *entry_point_from_quick_compiled_code_;
            } ptr_sized_fields_;
            static void *java_lang_reflect_ArtMethod_;
        };

    }
}

7.0ArtMethod头文件

代码语言:javascript
复制
/*
 *
 * Copyright (c) 2011 The Android Open Source Project
 * Copyright (c) 2016, alipay.com
 *
 * 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.
 */

/**
 *  art_7_0.h
 *
 * @author : sanping.li@alipay.com
 *
 */
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <string>
#include <memory>
#include <sys/mman.h>

#include <fcntl.h>
#include <dlfcn.h>

#include <stdint.h>    /* C99 */

typedef unsigned char u1;
typedef unsigned short u2;
typedef unsigned int u4;
typedef signed char s1;
typedef signed short s2;
typedef signed int s4;
namespace art {
    namespace mirror {
        class Object {
        public:
            static uint32_t hash_code_seed;
            uint32_t klass_;

            uint32_t monitor_;
        };

        class Class: public Object {
        public:
            enum Status {
                kStatusRetired = -2, // Retired, should not be used. Use the newly cloned one instead.
                kStatusError = -1,
                kStatusNotReady = 0,
                kStatusIdx = 1, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_.
                kStatusLoaded = 2,  // DEX idx values resolved.
                kStatusResolving = 3,  // Just cloned from temporary class object.
                kStatusResolved = 4,  // Part of linking.
                kStatusVerifying = 5,  // In the process of being verified.
                kStatusRetryVerificationAtRuntime = 6, // Compile time verification failed, retry at runtime.
                kStatusVerifyingAtRuntime = 7,  // Retrying verification at runtime.
                kStatusVerified = 8,  // Logically part of linking; done pre-init.
                kStatusInitializing = 9,  // Class init in progress.
                kStatusInitialized = 10,  // Ready to go.
                kStatusMax = 11,
            };
            // A magic value for reference_instance_offsets_. Ignore the bits and walk the super chain when
            // this is the value.
            // [This is an unlikely "natural" value, since it would be 30 non-ref instance fields followed by
            // 2 ref instance fields.]
            // Interface method table size. Increasing this value reduces the chance of two interface methods
            // colliding in the interface method table but increases the size of classes that implement
            // (non-marker) interfaces.
            // 'Class' Object Fields
            // Order governed by java field ordering. See art::ClassLinker::LinkFields.
            uint32_t annotation_type_;

            // Defining class loader, or null for the "bootstrap" system loader.
            uint32_t class_loader_1;
            // For array classes, the component class object for instanceof/checkcast
            // (for String[][][], this will be String[][]). null for non-array classes.
            uint32_t component_type_;
            // DexCache of resolved constant pool entries (will be null for classes generated by the
            // runtime such as arrays and primitive classes).
            uint32_t dex_cache_;
            // The interface table (iftable_) contains pairs of a interface class and an array of the
            // interface methods. There is one pair per interface supported by this class.  That means one
            // pair for each interface we support directly, indirectly via superclass, or indirectly via a
            // superinterface.  This will be null if neither we nor our superclass implement any interfaces.
            //
            // Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()".
            // Invoke faceObj.blah(), where "blah" is part of the Face interface.  We can't easily use a
            // single vtable.
            //
            // For every interface a concrete class implements, we create an array of the concrete vtable_
            // methods for the methods in the interface.
            uint32_t iftable_;
            // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
            uint32_t name_;
            // The superclass, or null if this is java.lang.Object or a primitive type.
            //
            // Note that interfaces have java.lang.Object as their
            // superclass. This doesn't match the expectations in JNI
            // GetSuperClass or java.lang.Class.getSuperClass() which need to
            // check for interfaces and return null.
            uint32_t super_class_;

            // If class verify fails, we must return same error on subsequent tries. We may store either
            // the class of the error, or an actual instance of Throwable here.
            uint32_t verify_error_;
            // Virtual method table (vtable), for use by "invoke-virtual".  The vtable from the superclass is
            // copied in, and virtual methods from our class either replace those from the super or are
            // appended. For abstract classes, methods may be created in the vtable that aren't in
            // virtual_ methods_ for miranda methods.
            uint32_t vtable_;
            // Access flags; low 16 bits are defined by VM spec.
            // Note: Shuffled back.
            uint32_t access_flags_;
            // Short cuts to dex_cache_ member for fast compiled code access.
            uint64_t dex_cache_strings_;

            // instance fields
            //
            // These describe the layout of the contents of an Object.
            // Note that only the fields directly declared by this class are
            // listed in ifields; fields declared by a superclass are listed in
            // the superclass's Class.ifields.
            //
            // ArtFields are allocated as a length prefixed ArtField array, and not an array of pointers to
            // ArtFields.
            uint64_t ifields_;
            // Pointer to an ArtMethod length-prefixed array. All the methods where this class is the place
            // where they are logically defined. This includes all private, static, final and virtual methods
            // as well as inherited default methods and miranda methods.
            //
            // The slice methods_ [0, virtual_methods_offset_) are the direct (static, private, init) methods
            // declared by this class.
            //
            // The slice methods_ [virtual_methods_offset_, copied_methods_offset_) are the virtual methods
            // declared by this class.
            //
            // The slice methods_ [copied_methods_offset_, |methods_|) are the methods that are copied from
            // interfaces such as miranda or default methods. These are copied for resolution purposes as this
            // class is where they are (logically) declared as far as the virtual dispatch is concerned.
            //
            // Note that this field is used by the native debugger as the unique identifier for the type.
            uint64_t methods_;

            // Static fields length-prefixed array.
            uint64_t sfields_;

            // Class flags to help speed up visiting object references.
            uint32_t class_flags_;

            // Total size of the Class instance; used when allocating storage on gc heap.
            // See also object_size_.
            uint32_t class_size_;
            // Tid used to check for recursive <clinit> invocation.
            pid_t clinit_thread_id_;
            // ClassDef index in dex file, -1 if no class definition such as an array.
            // TODO: really 16bits
            int32_t dex_class_def_idx_;
            // Type index in dex file.
            // TODO: really 16bits
            int32_t dex_type_idx_;
            // Number of instance fields that are object refs.
            uint32_t num_reference_instance_fields_;
            // Number of static fields that are object refs,
            uint32_t num_reference_static_fields_;
            // Total object size; used when allocating storage on gc heap.
            // (For interfaces and abstract classes this will be zero.)
            // See also class_size_.
            uint32_t object_size_;
            // The lower 16 bits contains a Primitive::Type value. The upper 16
            // bits contains the size shift of the primitive type.
            uint32_t primitive_type_;
            // Bitmap of offsets of ifields.
            uint32_t reference_instance_offsets_;
            // State of class initialization.
            Status status_;
            // The offset of the first virtual method that is copied from an interface. This includes miranda,
            // default, and default-conflict methods. Having a hard limit of ((2 << 16) - 1) for methods
            // defined on a single class is well established in Java so we will use only uint16_t's here.
            uint16_t copied_methods_offset_;

            // The offset of the first declared virtual methods in the methods_ array.
            uint16_t virtual_methods_offset_;
            // TODO: ?
            // initiating class loader list
            // NOTE: for classes with low serialNumber, these are unused, and the
            // values are kept in a table in gDvm.
            // InitiatingLoaderList initiating_loader_list_;
            // The following data exist in real class objects.
            // Embedded Imtable, for class object that's not an interface, fixed size.
            // ImTableEntry embedded_imtable_[0];
            // Embedded Vtable, for class object that's not an interface, variable size.
            // VTableEntry embedded_vtable_[0];
            // Static fields, variable size.
            // uint32_t fields_[0];
            // java.lang.Class
            static uint32_t java_lang_Class_;
        };

        class ArtField {
        public:
            uint32_t declaring_class_;
            uint32_t access_flags_;
            uint32_t field_dex_idx_;
            uint32_t offset_;
        };

        class ArtMethod {
        public:

            // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
            // The class we are a part of.
            uint32_t declaring_class_;
            // Access flags; low 16 bits are defined by spec.
            uint32_t access_flags_;
            /* Dex file fields. The defining dex file is available via declaring_class_->dex_cache_ */
            // Offset to the CodeItem.
            uint32_t dex_code_item_offset_;
            // Index into method_ids of the dex file associated with this method.
            uint32_t dex_method_index_;
            /* End of dex file fields. */
            // Entry within a dispatch table for this method. For static/direct methods the index is into
            // the declaringClass.directMethods, for virtual methods the vtable and for interface methods the
            // ifTable.
            uint16_t method_index_;

            // The hotness we measure for this method. Incremented by the interpreter. Not atomic, as we allow
            // missing increments: if the method is hot, we will see it eventually.
            uint16_t hotness_count_;
            // Fake padding field gets inserted here.
            // Must be the last fields in the method.
            // PACKED(4) is necessary for the correctness of
            // RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size).
            struct PtrSizedFields {
                // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
                ArtMethod** dex_cache_resolved_methods_;

                // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
                void* dex_cache_resolved_types_;

                // Pointer to JNI function registered to this method, or a function to resolve the JNI function,
                // or the profiling data for non-native methods, or an ImtConflictTable.
                void* entry_point_from_jni_;

                // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
                // the interpreter.
                void* entry_point_from_quick_compiled_code_;
            } ptr_sized_fields_;

        };

    }

}
编写native方法

7.0以下

代码语言:javascript
复制
#include <jni.h>
#include "art_method.h"

extern "C"
JNIEXPORT void JNICALL
Java_com_aruba_andfixapplication_DexManager_replaceArt(JNIEnv *env, jobject instance,
                                                       jobject wrongMethod, jobject rightMethod) {
//    art虚拟机替换  art  ArtMethod  ---》Java方法
    art::mirror::ArtMethod *wrong = (art::mirror::ArtMethod *) env->FromReflectedMethod(
            wrongMethod);
    art::mirror::ArtMethod *right = (art::mirror::ArtMethod *) env->FromReflectedMethod(
            rightMethod);

    wrong->declaring_class_ = right->declaring_class_;

    wrong->dex_code_item_offset_ = right->dex_code_item_offset_;
    wrong->dex_cache_resolved_methods_ = right->dex_cache_resolved_methods_;
    wrong->dex_cache_resolved_types_ = right->dex_cache_resolved_types_;
    wrong->access_flags_ = right->access_flags_;
    wrong->method_index_ = right->method_index_;
    wrong->dex_method_index_ = right->dex_method_index_;
    wrong->ptr_sized_fields_.entry_point_from_jni_ = right->ptr_sized_fields_.entry_point_from_jni_;
    wrong->ptr_sized_fields_.entry_point_from_quick_compiled_code_ = right->ptr_sized_fields_.entry_point_from_quick_compiled_code_;
    wrong->ptr_sized_fields_.entry_point_from_interpreter_ = right->ptr_sized_fields_.entry_point_from_interpreter_;
}

7.0

代码语言:javascript
复制
#include <jni.h>
#include "art_7_0.h"

extern "C"
JNIEXPORT void JNICALL
Java_com_aruba_andfixapplication_DexManager_replaceArt7(JNIEnv *env, jobject instance,
                                                        jobject wrongMethod, jobject rightMethod) {
//    art虚拟机替换  art  ArtMethod  ---》Java方法
    art::mirror::ArtMethod *wrong = (art::mirror::ArtMethod *) env->FromReflectedMethod(
            wrongMethod);
    art::mirror::ArtMethod *right = (art::mirror::ArtMethod *) env->FromReflectedMethod(
            rightMethod);

    wrong->declaring_class_ = right->declaring_class_;

    wrong->dex_code_item_offset_ = right->dex_code_item_offset_;
    wrong->method_index_ = right->method_index_;
    wrong->dex_method_index_ = right->dex_method_index_;


    //入口
    wrong->ptr_sized_fields_.entry_point_from_jni_ = right->ptr_sized_fields_.entry_point_from_jni_;
    //机器码模式
    wrong->ptr_sized_fields_.entry_point_from_quick_compiled_code_ = right->ptr_sized_fields_.entry_point_from_quick_compiled_code_;

    //  不一样
    wrong->ptr_sized_fields_.entry_point_from_jni_ = right->ptr_sized_fields_.entry_point_from_jni_;
    wrong->ptr_sized_fields_.dex_cache_resolved_methods_ = right->ptr_sized_fields_.dex_cache_resolved_methods_;
    wrong->ptr_sized_fields_.dex_cache_resolved_types_ = right->ptr_sized_fields_.dex_cache_resolved_types_;
    wrong->hotness_count_ = right->hotness_count_;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在so插件化原理,hook技术实现andfix热修复中,只实现了dalvik虚拟机中的热修复,安卓5.0后,谷歌彻底抛弃dalvik虚拟机,改用art虚拟机。
    • 在dalvik虚拟机中,应用启动首先会加载dex成class字节码,然后采用JIT技术,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码(CPU真正识别二进制),虽然转换时会利用缓存技术优化,但还是会造成应用运行速度。
      • 在art虚拟机中,在应用安装时,就通过dex2oat工具把dex文件转换为oat文件,oat文件中同时存放着字节码和机器码,这就造成了art虚拟机下安装应用比较慢,应用运行速度却大大提升了。
        • 上次我们在api19以下的情况,将两个Method对象传给native层进行函数指针替换,今天来做19以上的适配
          • 7.0的方法结构体和其他的不同,并且andfix只支持到7.0
            • 编写native方法
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档