告别手动埋点!Android 无侵入式数据采集方案深度解析

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: 传统的Android应用监控方案需要开发者在代码中手动添加埋点,不仅侵入性强、工作量大,还难以维护。本文深入探讨了基于字节码插桩技术的无侵入式数据采集方案,通过Gradle插件 + AGP API + ASM的技术组合,实现对应用性能、用户行为、网络请求等全方位监控,真正做到零侵入、易集成、高稳定。

作者:路锦(小蘭)


Android 应用数据采集背景


在移动应用开发领域,对应用性能(APM)和用户体验的实时监控至关重要。传统的监控方案通常要求开发者在代码中手动添加和初始化 SDK,并在需要监控的业务逻辑处(如网络请求、页面跳转、用户点击等)手动调用埋点代码。


这种方式存在诸多痛点:


  • 侵入性强监控代码与业务代码高度耦合,增加了代码的复杂度和维护成本。
  • 工作量大:对于庞大的应用,手动埋点耗时耗力,且容易遗漏关键的监控点。
  • 难以维护:业务逻辑的频繁变更可能导致埋点代码失效或需要同步修改,增加了出错的风险。
  • 接入成本高:新项目或新团队成员需要花费时间学习和理解埋点规范。

1761276834516_2FA62CF4-97DD-4fd4-A941-A83B3AA8CCE2.png

为了解决以上问题,实现监控能力的自动化、全面化和降低接入成本,无侵入式的插桩方案应运而生。其核心目标是在不修改应用源码的情况下,通过在编译打包过程中自动注入监控探针,实现对应用行为的全面监控,将开发者从繁琐的埋点工作中解放出来。


核心挑战与关注点

在设计和实现一套稳定、高效的无侵入插桩方案时,我们必须面对并解决以下核心挑战:

1761276855783_781DFD43-E901-4dd3-8549-CEB1060EDC28.png

1)Android 生态的碎片化挑战

Android 系统的开放性导致其生态存在严重的碎片化问题,这在构建工具层面尤为突出。Android Gradle 插件(AGP)版本迭代迅速,核心编译 API 频繁变更(例如从 Transform API 到 Instrumentation API 的迁移)。插桩方案必须能够动态适配不同的 AGP 版本,否则将无法在开发者的多样化环境中正常工作。


2)第三方插件的兼容性与冲突风险

市面上的 APM 或功能增强插件(如其他监控工具、热修复框架等)大多采用类似的字节码插桩技术。如果我们的插桩方案与其他插件在同一位置修改了同一段代码,极易引发构建错误或运行时冲突。因此,必须设计一套机制来避免“重复插桩”,并尽可能地与其他插件和平共存。


3)插桩代码的健壮性与独立性

通过插件注入到用户代码中的探针必须具备极高的健壮性和独立性。一个常见且致命的问题是:如果用户在项目中应用了插桩插件,但忘记在代码中初始化主 SDK,那么注入的探针代码在调用 SDK 功能时可能会因为依赖未就绪而导致空指针(NullPointerException)等严重崩溃。插桩方案必须保证即使在主 SDK 未启动的情况下,应用也不会崩溃。


Android 无侵入式采集方案探讨


业界主流的无侵入插桩方案主要围绕在编译期对代码进行修改,采集原理均基于 AOP 思想,AOP 的思想主张将“横切关注点”从业务逻辑中抽离出来,独立地封装到一个被称为“切面”(Aspect)的模块中,然后通过声明的方式,告诉程序应该在“什么时机”、“什么地方”去执行这些切面中的逻辑,而不需要去修改业务逻辑的源码。


应用数据采集场景分析

Android 端的无侵入采集种类繁多,但核心思想都是通过自动化手段在不修改业务代码的前提下,捕获应用运行时的各种事件和数据。按照 Android 应用常见的采集场景分类,我们分别探讨每种场景对应的方案选型。


1. 用户行为与页面采集

这类采集的目标是了解用户如何与 App 交互,以及页面的生命周期。


  • 页面(Activity/Fragment)生命周期采集
  • 技术方案:
  • Activity:Application.registerActivityLifecycleCallbacks。
  • Fragment:AndroidX 可用生命周期回调;老版 android.app.Fragment 常用字节码插桩在 onResume/onPause/onViewCreated 等方法前后注入。
  • 采集数据:页面浏览路径、页面加载时长、PV/UV 统计。
  • 用户交互事件(点击、滑动等)
  • 技术方案:主流方案是字节码插桩,例如通过 ASM 操作字节码。
  • 代理监听器:插桩修改 setOnClickListener 等设置监听器的方法,将其中的监听器替换为一个代理监听器。代理类在执行原始逻辑前后加入采集代码。这种方式可以精确采集到控件信息。
  • Hook 方法:通过字节码插桩技术,在编译期直接向处理点击事件的方法中注入采集代码来实现。
  • 采集数据:控件点击事件(Action)、控件的标识(ID、文本)、关联页面。

2. 网络请求监控

目标是采集 App 发出的所有 HTTP/HTTPS 请求的性能和成功率。

  • 技术方案:同样以字节码插桩为主,针对不同的网络库进行 Hook。
  • OkHttp:这是目前最主流的网络库。可以通过插桩  OkHttpClient.Builder.build() 方法,在其中添加一个自定义的拦截器来获取请求的全部信息,并计算请求性能。
  • HttpURLConnection:这是 Android 原生的网络请求方式。通常插桩 URL.openConnection() 方法,将其返回的 HttpURLConnection 对象替换为一个代理对象,从而在代理类中监控回调方法,实现数据采集。
  • 其他网络库:如 Retrofit 等,它们的底层逻辑通常也是基于OkHttp 或HttpURLConnection。
  • 采集数据:URL、请求方法、HTTP 状态码、请求耗时(DNS、TCP、SSL、总耗时等)、请求和响应体大小、TraceID(用于分布式链路追踪)。

3. 应用性能监控

  • 应用启动耗时
  • 技术方案:
  • 冷启动、热启动:通常通过 Android API 采集。
  • UI 卡顿与长任务
  • 技术方案:
  • Looper 监控:通过 Looper.getMainLooper().setMessageLogging() 设置一个自定义的 Printer,可以监控到主线程 Looper 处理每个 Message 的开始和结束。如果处理单个 Message 耗时过长,即可判定为一次卡顿或长任务,并抓取主线程堆栈。
  • ANR (Application Not Responding)
  • 技术方案:通用做法是启动一个独立的“看门狗”线程,该线程定期向主线程的 Looper 发送一个任务。如果在规定时间(如 4-5 秒)内该任务没有被执行,就认为主线程被阻塞,此时“看门狗”线程会抓取主线程的堆栈信息,作为 ANR 日志上报。

4. 崩溃监控

  • Java/Kotlin 崩溃
  • 技术方案:使用 Thread.setDefaultUncaughtExceptionHandler() 设置一个全局的未捕获异常处理器。当应用崩溃时,这个处理器会被调用,SDK 可以在这里捕获异常信息、堆栈、线程状态等,保存后上报。
  • Native (C/C++) 崩溃
  • 技术方案:通过 JNI 实现。使用 Linux 的 Signal 信号处理机制,注册对 SIGSEGV, SIGABRT, SIGILL 等致命信号的监听。当 Native 代码崩溃触发这些信号时,信号处理器被回调。在处理器中,可以记录下崩溃现场保存为文件,待下次 App 启动时上报。

5. WebView监控

  • 技术方案:核心是 JS 探针注入。
  • 通过字节码插桩 Hook WebView 的相关方法,插入 JS 采集探针实现采集。

小结:根据采集场景分析,我们发现在 Android 无侵入式采集中,最需要关注的技术是字节码插桩。


字节码插桩技术

  • 技术介绍:这是目前 Android 领域最主流和最强大的无侵入技术。它利用 Android Gradle 插件(AGP)在编译过程中提供的 API(如 Transform API 或新的 Instrumentation API),在 .class文件被编译.dex 文件之前,对其字节码进行扫描和修改。其中,ASM 是一个高性能、轻量级的 Java 字节码操作和分析框架。它提供了丰富的 API,可以像操作对象一样对类的结构、字段、方法和指令进行精细化的增删改查。
  • 原理:

image.png

  1. 通过插件注册一个在编译构建阶段执行的任务。
  2. 该任务遍历项目源码和所有依赖库(jar/aar)中的 .class 文件。
  3. 使用 ASM 的 ClassReader 读取每个类的字节码。
  4. 通过自定义的 ClassVisitorMethodVisitor 访问类和方法的结构。
  5. MethodVisitor 中找到需要注入代码的目标位置(如方法入口、方法出口、或者某个特定指令前后),并插入新的字节码指令。
  6. 使用 ClassWriter修改后的字节码写回,替换原文件。
  • 优点:控制粒度最细,功能最为强大,几乎可以实现任意逻辑的注入。性能开销极低,是实现高性能监控 SDK 的首选方案。
  • 构建 API 演进与兼容
  • Transform API:AGP 8 起移除。
  • Instrumentation API:AGP 7 引入,AGP 8 强烈推荐且基本强制使用。
  • 插件需动态选择:优先使用 Instrumentation API;旧环境降级到 Transform。


无侵入式插桩方案实践


基于上述Android无侵入式采集方案分析,我们这里使用字节码插桩技术,以点击行为采集场景为例,进行一次完整的无侵入式采集方案实践。


核心思想

章节一中我们提到了无侵入式采集需要面临的挑战,这里我们整理了以下三个核心思想,来解决上述问题。


AGP 版本动态适配策略

为了适应 Android Gradle 插件的快速迭代,在插件开发中需要对新旧版本的 AGP 做兼容处理,以不同版本的AGP兼容性特点为例:


  • 老版本AGP (Legacy):插件会使用 AGP 旧版的  TransformAPI 来处理字节码的转换逻辑。
  • AGP 7+:插件会采用 Google 官方推荐的 Instrumentation API 来负责实现新版 API 的对接,这种方式更高效、更稳定。


在插件入口时可以在运行时动态检测 AGP 版本,并选择相应的实现,对开发者完全透明。这里我们提供一个基于不兼容 API 的适配策略。


MyApmPluginpublic class MyApmPlugin implements Plugin<Project> {
   @Override
    public void apply(Project project) {
        boolean hasAsmFactory = classExists("com.android.build.api.instrumentation.AsmClassVisitorFactory");
        boolean hasTransform = classExists("com.android.build.api.transform.Transform");
        if (hasAsmFactory) {
            // AGP 7+,使用 Instrumentation API(推荐)
            new Agp7PlusImpl(project).init();
        } else if (hasTransform) {
            // 老版本,使用 Transform API
            new LegacyTransformImpl(project).init();
        } else {
            project.getLogger().warn("No supported AGP API found. Plugin disabled.");
        }
    }
}


兼容性设计,避免插件冲突

为了最大限度地兼容第三方插件并防止冲突,我们提供了以下方案:


  • 黑名单跳过系统包、常见 APM/热修复/加固框架、自身 SDK。
  • 白名单可选,只处理应用/业务相关包,最大程度降低误伤与冲突。
  • 幂等插桩避免重复注入,例如 tag 标记、instanceOf 判断。
  • 注解式控制可选,支持 @NoTrack、@TrackIgnore 注解,编译期间扫描后跳过特定类/方法,给业务兜底控制权。
  • 插桩失败回退单类插桩失败时,记录日志并回退为原始字节码,构建继续。


这里是一个黑名单过滤样例代码:


public class ClassInstrumentChecker {
    private static final List<String> BLACKLISTED_PREFIXES = Arrays.asList(
        // 常见系统库、协程等应该避免插桩
        "java/",
        "javax/",
        "kotlin/", 
        "kotlinx/",
        "android/",
        "androidx/",
        "com/my/apm/sdk/" // 自身 SDK,避免递归处理
        // 其他 APM 或性能监控产品等
        "com/networkbench/",
        "com/sensorsdata/",
        "com/tencent/qapmsdk/",
        // 常见热修复或加固框架
        "com/tencent/tinker/",
        "com/taobao/sophix/",
        // 自身 SDK,避免重复处理
        "com/my/apm/sdk/"
    );
    /**
     * 检查一个类是否应该被插桩。
     * @param className 类的名称 (e.g., "com/example/myapp/MyClass")
     * @return 如果应该被插桩,返回 true;否则返回 false。
     */
    public static boolean shouldInstrument(String className) {
        // 排除 R 文件和 BuildConfig
        if (className.contains("/R$") || className.endsWith("/R") || className.endsWith("/BuildConfig")) {
            return false;
        }
        for (String prefix : BLACKLISTED_PREFIXES) {
            if (className.startsWith(prefix)) {
                return false; // 命中黑名单,跳过
            }
        }
        return true; // 未命中,可以插桩
    }
}


安全插桩,确保代码独立与稳定

这是保障方案健壮性的核心。我们秉持“最少侵入”和“绝对安全”的原则,确保注入的代码稳定且无副作用。


  • 不替换原生逻辑:我们的插桩始终是在原生方法逻辑的“之前”或“之后”进行补充,而不是替换。例如,在监听网络请求时,我们会先调用 SDK 的追踪方法,然后通过 super.visitMethodInsn() 继续执行原生的网络调用指令,保证应用原有功能不受任何影响。
  • 不引入第三方依赖:注入的字节码指令极其精简,仅包含对我们自身 SDK 中特定静态方法的调用(如 TrackInstrument.trackViewOnClick(...)),不引入任何新的外部库依赖,保持了插桩点的纯净性。
  • 探针代码独立运行与异常隔离:这是解决“SDK 未初始化”问题的关键。所有被注入的探针最终调用的 SDK 工具类(如 TrackInstrument)内部都遵循了严格的防御性编程。在该工具类的入口处,会首先检查主 SDK 是否已成功初始化。插桩部分发生异常时不影响原始业务逻辑,未初始化时所有插桩代码会立即静默返回,不执行任何实质性操作确保了即使在极端情况下注入的探针也不会引发任何崩溃。
  • Kotlin 与 Jetpack Compose 插桩补充:
  • 内联函数 (inline):inline 函数体在编译期被直接复制到调用处,可能改变最终方法布局与调用栈,插桩目标应是其内部调用的非内联方法,而非 inline 函数本身
  • Jetpack Compose 点击事件 (Modifier.clickable):通常通过 Modifier.clickable 实现,需另行在 Compose Runtime 层或特定包装函数处插桩(或在 UI Toolkit 层提供可选的轻量扩展,而非硬插桩)。
  • Lambda 表达式的实现差异:Lambda 的字节码实现方式不唯一。为兼容低版本安卓,编译器可能将其“脱糖” (Desugar) 为匿名内部类,而非现代的 invokedynamic 实现。两种模式生成的方法签名(类名、方法名、是否静态)完全不同,插桩方案必须兼容这两种情况,以防因签名不匹配而失效。


这里提供一个插桩方法样例,给 OnClick 事件插入我们需要的日志采集代码。


public class OnClickMethodVisitor extends AdviceAdapter {
    public OnClickMethodVisitor(MethodVisitor mv, int access, String name, String desc) {
        super(Opcodes.ASM9, mv, access, name, desc);
    }
    @Override
    protected void onMethodEnter() {
        super.onMethodEnter();
        // 在 onClick(Landroid/view/View;)V 方法的入口处插入代码
        mv.visitVarInsn(Opcodes.ALOAD, 1); // 加载第一个参数 (View 对象) 到操作数栈
        // 调用我们自己的静态工具方法来处理点击事件
        mv.visitMethodInsn(
            Opcodes.INVOKESTATIC, // 静态方法调用
            "com/my/apm/sdk/TrackInstrument", // 包含追踪方法的类
            "trackViewOnClick", // 方法名
            "(Landroid/view/View;)V", // 方法描述符
            false // 非接口方法
        );
    }
}


public class TrackInstrument {
    public static void trackViewOnClick(View view) {
        try {
            // 核心安全设计:检查 SDK 是否已初始化
            if (!MyApmAgent.isInitialized() || view == null) {
                return; // 如果未初始化,则静默返回,不执行任何操作
            }
            // 如果已初始化,则执行正常的事件采集逻辑
            String viewId = getViewId(view);
            MyApmAgent.get().logUserAction("click", viewId);
        } catch (Throwable ignored) {
            // 完全隔离异常,避免影响业务
        }
    }
}


插桩实践

结合上述核心思想,我们完整地串联起一个 onClick 点击数据的采集方案。方案的核心是一个自定义的 Gradle 插件,当 Android 应用集成此插件后,它会自动注入到应用的构建流程中,在编译期完成代码的自动化注入。


无论使用哪种 AGP API,核心的字节码修改逻辑都由 ASM 库驱动,整体流程如下:


1. 遍历 Class 文件

插件在执行时会获取到项目中的所有 .class 文件,包括源码编译的类和第三方库中的类。


// 代码样例: 在 Gradle Transform 中遍历输入文件
@Override
public void transform(TransformInvocation transformInvocation) {
    Collection<TransformInput> inputs = transformInvocation.getInputs();
    TransformOutputProvider outputProvider = transformInvocation.getOutputProvider();
    for (TransformInput input : inputs) {
        // 遍历 Jar 包
        for (JarInput jarInput : input.getJarInputs()) {
            File srcJar = jarInput.getFile();
            File destJar = outputProvider.getContentLocation(...);
            processJar(srcJar, destJar);
        }
        // 遍历目录
        for (DirectoryInput directoryInput : input.getDirectoryInputs()) {
            File srcDir = directoryInput.getFile();
            File destDir = outputProvider.getContentLocation(...);
            processDirectory(srcDir, destDir);
        }
    }
}


2. ASM 分析与修改

  • 每个类文件都会被 ClassAdapter 访问。该类是一个 ClassVisitor,它会首先进行过滤,通过 isClassShouldInstrument 方法中的黑名单,跳过对系统库、其他 APM 产品、SDK 自身以及一些已知会产生冲突的第三方库的插桩,以保证稳定性和兼容性。
  • 对于需要处理的类,核心插桩任务交由 MyMethodAdapter(一个 AdviceAdapter 的子类)完成。它会遍历类中的每一个方法。


// 代码样例: ClassVisitor 和 MethodVisitor 的责任链
public class MyClassAdapter extends ClassVisitor {
    private String className;
    public MyClassAdapter(ClassVisitor classVisitor) {
        super(Opcodes.ASM9, classVisitor);
    }
    @Override
    public void visit(int version, int access, String name, ...) {
        super.visit(version, access, name, ...);
        this.className = name;
    }
    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, ...) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, ...);
        // 检查此类是否在黑名单中
        if (!ClassInstrumentChecker.shouldInstrument(className)) {
            return mv; // 在黑名单中,返回原始 MethodVisitor,不处理
        }
        // 如果需要处理,则返回我们自定义的 MethodVisitor
        return new MyMethodAdapter(mv, access, name, descriptor);
    }
}


3. 采集探针注入 (Hook)

  • MyMethodAdapteronMethodEnter 方法会在方法体的最开始处插入代码。
  • MyHookConfig.java 文件中预定义了所有需要 Hook 的目标方法,例如点击行为的 onClick 方法等。
  • MyMethodAdapter 访问到这些目标方法时,就会在方法开头插入对 TrackInstrument 中对应追踪方法的调用(如 trackViewOnClick),从而实现对页面生命周期、用户点击、菜单选择等事件的自动采集。
  • Lambda 表达式处理通过 visitInvokeDynamicInsn 指令对 Java 8 的 Lambda 表达式进行了特殊处理,能够准确识别出作为监听器实现的 Lambda 表达式(如 view.setOnClickListener(v -> ...)),并对其进行正确的插桩。


public class OnClickAdviceAdapter extends AdviceAdapter {
  protected OnClickAdviceAdapter(MethodVisitor mv, int access, String name, String desc) {
  super(Opcodes.ASM9, mv, access, name, desc);
}
@Override protected void onMethodEnter() {
  // 加载参数 View(index=1)
visitVarInsn(ALOAD, 1);
// 调用静态方法 TrackInstrument.trackViewOnClick(View)
visitMethodInsn(INVOKESTATIC,
                "com/my/apm/sdk/TrackInstrument",
                "trackViewOnClick",
                "(Landroid/view/View;)V",
                false);
}
}


// 代码样例: MethodVisitor 的实现, 包含 Lambda 处理
public class MyMethodAdapter extends AdviceAdapter {
    private final String methodNameDesc;
    private final String className;
    public MyMethodAdapter(MethodVisitor mv, int access, String name, String desc, String className) {
        super(Opcodes.ASM9, mv, access, name, desc);
        this.methodNameDesc = name + desc;
        this.className = className;
    }
    @Override
    protected void onMethodEnter() {
        super.onMethodEnter();
        // 检查当前方法是否为普通方法或已被标记的 Lambda 方法
        MyHookConfig.HookCell hookCell = MyHookConfig.HOOK_METHODS.get(methodNameDesc);
        if (hookCell == null) {
            hookCell = MyHookConfig.LAMBDA_METHODS_TO_HOOK.get(methodNameDesc);
        }
        if (hookCell != null) {
            // 注入探针代码... (此部分逻辑见核心思想中的样例)
        }
    }
    @Override
    public void visitInvokeDynamicInsn(String name, String descriptor, Handle bsm, Object... bsmArgs) {
        super.visitInvokeDynamicInsn(name, descriptor, bsm, bsmArgs);
        try {
            // 检查是否为我们关心的 Lambda 表达式, 例如 OnClickListener
            String samMethodDesc = ((Type) bsmArgs[0]).getDescriptor();
            if ("(Landroid/view/View;)V".equals(samMethodDesc)) {
                // 获取 Lambda 的方法体实现信息
                Handle implMethodHandle = (Handle) bsmArgs[1];
                String lambdaBodySignature = implMethodHandle.getName() + implMethodHandle.getDesc();
                // 将该 Lambda 的方法体标记为需要插桩,值为 onClick 的 HookCell
                MyHookConfig.LAMBDA_METHODS_TO_HOOK.put(lambdaBodySignature, MyHookConfig.HOOK_METHODS.get("onClick(Landroid/view/View;)V"));
            }
        } catch (Exception e) {
            // ignore
        }
    }
}


// 代码样例: Hook 配置类
public class MyHookConfig {
    public static final Map<String, HookCell> HOOK_METHODS = new HashMap<>();
    // 用于存储被识别出的、需要被插桩的 Lambda 方法体
    public static final Map<String, HookCell> LAMBDA_METHODS_TO_HOOK = new ConcurrentHashMap<>();
    static {
        HOOK_METHODS.put("onClick(Landroid/view/View;)V", new HookCell("trackViewOnClick", "(Landroid/view/View;)V"));
    }
    // ... 其他配置
}


4. 生成新类

所有修改完成后,ClassWriter 会生成新的字节码,替换原有的 .class 文件。这些被注入了监控探针的类文件最终会被打包进 APK 中,在应用运行时自动执行监控逻辑。


// 代码样例: ASM 生成新字节码的核心逻辑
public byte[] processClass(InputStream classInputStream) throws IOException {
    ClassReader classReader = new ClassReader(classInputStream);
    // ClassWriter 会在责任链的末端,负责将所有修改写入字节码
    ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
    // 启动访问者链,MyClassAdapter 是我们自定义的访问器
    classReader.accept(new MyClassAdapter(classWriter), ClassReader.EXPAND_FRAMES);
    // 返回包含所有修改的新字节码
    return classWriter.toByteArray();
}


总结


本文通过探讨 Gradle 插件 + AGP API + ASM 字节码插桩的插桩方案,实现了一套对业务代码零侵入、易于集成、可安全运行的自动化监控采集方案阿里云 RUM 针对 Android 端实现了对应用性能、稳定性、和用户行为的无侵入式采集 SDK。可以参考接入文档[1]体验使用。相关问题可以加入“RUM 用户体验监控支持群”(钉钉群号:67370002064)进行咨询。


相关链接:

[1] 接入文档

https://help.aliyun.com/zh/arms/user-experience-monitoring/access-to-android-applications

相关实践学习
通过轻量消息队列(原MNS)主题HTTP订阅+ARMS实现自定义数据多渠道告警
本场景将自定义告警信息同时分发至多个通知渠道的需求,例如短信、电子邮件及钉钉群组等。通过采用轻量消息队列(原 MNS)的主题模型的HTTP订阅方式,并结合应用实时监控服务提供的自定义集成能力,使得您能够以简便的配置方式实现上述多渠道同步通知的功能。
相关文章
|
3天前
|
弹性计算 人工智能 安全
云上十五年——「弹性计算十五周年」系列客户故事(第二期)
阿里云弹性计算十五年深耕,以第九代ECS g9i实例引领算力革新。携手海尔三翼鸟、小鹏汽车、微帧科技等企业,实现性能跃升与成本优化,赋能AI、物联网、智能驾驶等前沿场景,共绘云端增长新图景。
|
9天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
|
8天前
|
人工智能 自然语言处理 自动驾驶
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
|
8天前
|
云安全 人工智能 自然语言处理
阿里云x硅基流动:AI安全护栏助力构建可信模型生态
阿里云AI安全护栏:大模型的“智能过滤系统”。
|
9天前
|
编解码 自然语言处理 文字识别
Qwen3-VL再添丁!4B/8B Dense模型开源,更轻量,仍强大
凌晨,Qwen3-VL系列再添新成员——Dense架构的Qwen3-VL-8B、Qwen3-VL-4B 模型,本地部署友好,并完整保留了Qwen3-VL的全部表现,评测指标表现优秀。
661 7
Qwen3-VL再添丁!4B/8B Dense模型开源,更轻量,仍强大
|
4天前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
|
11天前
|
存储 机器学习/深度学习 人工智能
大模型微调技术:LoRA原理与实践
本文深入解析大语言模型微调中的关键技术——低秩自适应(LoRA)。通过分析全参数微调的计算瓶颈,详细阐述LoRA的数学原理、实现机制和优势特点。文章包含完整的PyTorch实现代码、性能对比实验以及实际应用场景,为开发者提供高效微调大模型的实践指南。
784 2
|
2天前
|
编解码 文字识别 算法
一张图能装下“千言万语”?DeepSeek-OCR 用视觉压缩长文本,效率提升10倍!
一张图能装下“千言万语”?DeepSeek-OCR 用视觉压缩长文本,效率提升10倍!
340 10