走进jvm

告别‘火龙’:实测BES2800/RK2108等主流芯片,聊聊AI眼镜的功耗与散热‘内卷’实战 本文深入探讨了AI智能眼镜在功耗与散热方面的挑战,重点分析了恒玄BES2800和瑞芯微RK2108等主控芯片的能效表现。通过实测数据和优化策略,揭示了在6nm工艺、异构计算和系统级散热方案下的实战经验,为AI眼镜的功耗管理提供了实用解决方案。 阅读详情

java源代码是怎么被机器识别并执行的呢?答案是java虚拟机,即java virtual machine.

1、字节码(也称中间码,bytecode)

一、java所有的指令有200个左右,一个字节(8位)可以存储256种不同的指令信息,一个这样的字节称为字节码(bytecode).在代码的执行过程种,jvm将字节码解释执行,屏蔽了对底层操作系统的依赖;jvm也可以将字节码编译执行,如果是热点代码,会通过JIT(Just in time)动态地翻译为机器码,提高执行效率.

二、字节码指令

1.加载或存储指令

    1)、将局部变量加载到操作栈中.(如 ILOAD 将int类型的局部变量压入栈 和 ALOAD将对象引用的局部变量压入栈)等
    2)、从操作栈顶存储到局部变量表.如ISTORE、ASTORE等.
    3)、将常量加载到操作栈顶,这是极为高频使用的指令.如ICONST、BIPUSH、SIPUSH、LDC等.
2.运算指令
    对两个操作栈帧上的值进行运算,并把结果写入操作栈顶,如IADD、IMUL等
3.类型转换指令
    显示转换两种不同的数值类型.如I2L、D2F等
4.对象创建与访问指令
    1)、创建对象指令.如NEW、NEWARRAY等.
    2)、访问属性指令.如GETFIELD、PUTFIELD 、GETSTATIC等.
    3)、检查实例类型指令.如INSTANCEOF、 CHECKCAST等.
5.操作栈管理指令
    1)、出栈操作.如POP即一个元素,POP2即两个元素.
    2)、复制栈顶元素并压入栈.如DUP.
6.方法调用与返回指令
    常见指令如下:
    (1)、INVOKEVIRTUAL指令:调用对象的实例方法.
    (2)、INVOKESPECIAL指令:调用实例初始化方法、私有方法、父类方法等.
    (3)、INVOKESTATIC指令:调用类静态方法.
    (4)、RETURN指令:返回VOID类型.
7.同步指令
    JVM使用方法结构种的ACC_SYNCHRONIZED标志同步方法,指令集中有MONTORENTER和MONITOREXIT支持synchonized语义.

 
三、字节码生成过程

我们编写好的.java文件是源代码文件,并不能交给机器直接执行,需要将其编译成为字节码甚至机器码文件.那么静态编译器如何把源码转化称字节码的呢?如图所示:

词法解析是通过空格分隔出单词、操作符、控制符等信息,将其形成token信息流,传递给语法解析器;在语法解析时,把词法解析得到的token信息流按照java语法规则组装称一颗语法树.在语义分析阶段,需要检查关键字的使用是否合理、类型是否匹配、作用域是否正确等;当语义分析完成之后,即可生产字节码.

字节码必须通过类加载过程加载到jvm环境后,才可以执行.执行有三种模式:第一,解释执行;第二,JIT编译执行;第三,JIT编译与解释混合执行(主流jvm默认执行模式).混合执行模式的优势在于解释器在启动时先执行.省去编译时间.JIT的作用是将java字节码动态地编译成可以直接发送给处理器指令执行的机器码.

2、类加载过程

在冯.诺依曼定义的计算机模型中,任何程序都需要加载到内存才能与cpu进行交流.字节码.class文件同样需要加载到内存中,才可以实例化类.在加载类时,使用的是parent delegation model,译为双亲委派模型.

java的类加载器是一个运行时核心基础设施模块,如上图,主要是在启动之初进行类的Load、Link、Init,即加载、链接、初始化.

一、加载步骤

第一步,Load阶段读取类文件产生二进制流,并转化为特定的数据结构,初步校验cafe babe魔法数、常量池、文件长度、是否有父类等,然后创建对应类的java.lang.Class实例.

第二步,Link阶段包括验证、准备、解析三个步骤.验证阶段是更详细的校验,比如final是否合规、类型是否正确、静态变量是否合理等;准备阶段是为静态变量分配内存,并设定默认值,解析类和方法确保类与类之间的相互引用的正确性,完成内存结构布局.

第三步,Init阶段执行类构造器<clinit> (class init)方法,如果赋值运算是通过其他类的静态方法来完成的,那么会马上解析出另外一个类,在虚拟机栈中执行完毕后通过返回值进行赋值.

二、类加载器的层次

1)、bootstrap classloader

2)、platform classload(extension classloader)

3)、application classload

3、内存布局

一、Heap(堆区)

Heap是OOM故障最主要的发源地,它存储着几乎所有的实例对象,堆由垃圾收集器自动回收,堆区由各子线程共享使用.通常情况下,它占用的空间是所有内存区域最大的,但如果无节制地创建大量对象,也容易消耗所有的空间.

Heap大小可以通过如下参数设定:

-Xms256M -Xmx1024M 

ms是memory start 简称    mx是memory max简称

注意:在通常情况下,服务器在运行过程中,堆空间不断的扩容与回缩,势必形成不必要的系统压力,所以在线上生产环境中,jvm的Xms和Xmx设置成一样大小,避免在GC后调整堆大小时带来的额外压力.

堆分成两大块:新生代和老年代.对象产生之初在新生代,步入暮年时进入老年代,但是老年代也接纳在新生代无法容纳的超大对象.

新生代=1个Eden区+2个Survivor区.绝大部分对象在Eden区生成,当Eden区装填满的时候,会触发Young Garbage Collection,即YGC.

依然存活的对象会被移送到Survivor区.如果YGC移送的对象代Survivor区容量的上限,则直接交给类老年代.

每个对象都有一个计数器,每当YGC都会+1. -XX:MaxTenuringThreshold参数配置计数器的值到达某个阀值的时候,对象会从新生代晋升为老年代.

如果Survivor区无法放下,或者超大对象的阀值超过类上限,则尝试在老年代中进行分配;如果老年代也无法放下,则会触发Full Garbage Collection,即FGC.如果依然放不下,则抛出OOM.堆内存出现OOM的概率是所有内存耗尽异常中最高的.出错时的堆内信息堆解决问题非常有帮助,所以给jvm设置运行参数 -XX:+HeapDumpOnOutOfMemoryError,让jvm遇到oom异常时能输出堆内信息,特别是对相隔数月才出现的oom异常尤为重要.

二、Metaspace(元空间)

异常早在jdk8版本中,元空间的前身Perm区已经被淘汰.在jdk7及之前的版本中,只有hotspot才有Perm区,译为永生代,它在启动时固定了大小,很难进行调优,并且FGC时会移动类元信息.在某些场景下,如果动态加载类过多,容易产生Perm区的OOM.比如某个实际Web工程中,因为功能点比较多,在运行过程中,要不断动态的加载很多的类,经常出现致命错误:   xxxx java.lang.OutOfMemoryError:PermGen space.

为了解决该问题,需要设定运行参数-XX:MaxPermSize=1280M,如果部署到新机器上,往往会因为jvm参数没有修改导致故障再现.jdk8使用元空间替换永久代.在jdk8及以上版本中,设定MaxPermSize参数,jvm在启动的时候并不会报错,但会提示,suport was removed in 8.0.

三、JVM Stack(虚拟机栈)

栈(stack)是一个先进后出的数据结构,像子弹的弹夹,撞针只能访问位于顶部的那一颗子弹.相对于基于寄存器的运行环境来说,jvm是基于栈结构的运行环境.栈结构移植性更好,可控性更强.jvm中的虚拟机栈是描述java方法执行的内存区域,它是线程私有的.栈中的元素用来支持虚拟机进行方法调用,每个方法从开始调用到执行完成的过程,就是栈帧从入栈到出栈的过程.在活动线程中,只有位于栈顶的帧才是有效的,称为当前栈帧.正在执行的方法称为当前方法,栈帧是方法运行的基本结构.

在执行引擎运行时,所有指令都只能针对当前栈帧进行操作.而StackOverflowError表示请求溢出,导致内存耗尽,通常出现在递归的方法中.JVM能够横扫千军,虚拟机栈就是它的心腹大将,当前方法的栈帧,都是正在战斗的战场,其中的操作栈是参与战斗的士兵.

虚拟机栈通过压栈和出栈的方式,对每个方法对应的活动栈帧进行运算处理,方法正常执行结束,肯定会跳转到另一个栈帧上.在执行的过程中,如果出现异常,会进行异常回溯,返回地址通过异常处理表确定.栈帧在整个jvm体系中的地位颇高,包括局部变量表、操作栈、动态连接、方法返回地址等.

四、Native Method Stacks(本地方法栈)

本地方法栈(Native Mothod Stack) 在jvm内存布局中,也是线程对象私有的,但是虚拟机栈“主内”,而本地方法栈“主外”.这个“内外”是针对jvm而言的,本地方法栈为native方法服务.线程开始调用本地方法时,会进入一个不再受jvm约束的世界.本地方法可以通过JNI(java Native Interface)来访问虚拟机运行时的数据区,甚至可以调用寄存器,具有和jvm相同的能力和权限.当大量的本地方法出现时,势必会削弱jvm对系统的控制力,因为它的出错信息会比较黑盒.对于内存不足的情况,本地方法栈还是会抛出native heap OutOfMemory.

重点说一下JNI类本地方法.最著名的本地方法应该是System.currentTimeMillis(),JNI是java深度使用操作系统的特性功能,复用非java代码.但是在项目过程中,如果大量使用其他语言来实现JNI,就会丧失跨平台的特性,威胁到程序的稳定性.假如需要与本地代码交互,就可以用中间标准框架进行解耦,这样即使本地方法奔溃也不至于影响到jvm的稳定,当然,如果要求极高的执行效率、偏底层的跨进程操作等,可以考虑设计JNI调用方式.

五、Program Counter Register(程序计数寄存器)

在程序计数寄存器(PC)中,Register的命名源于CPU的寄存器,CPU只有把数据转载到寄存器才能够运行.寄存器存储指令相关的现场信息,由于CPU时间片轮限制,众多线程在并发执行过程中,任何一个确定的时刻,一个处理器或者多核处理器中的一个内核,只会执行某个线程中的一条指令.这样必然导致经常中断或恢复,如何保证分毫不差呢?每个线程在创建后,都会产生自己的程序计数器和栈帧,程序计数器用来存放执行指令的偏移量和行号指示器等,线程执行或恢复都要依赖程序计数器.程序计数器在各个线程之间互不影响,此区域也不会发送内存溢出异常.

最后,从线程共享的角度来看,堆和元空间是所有线程共享的,而虚拟机栈、本地方法栈、程序计数器都是线程内部私有的.

4、对象实例化

java是面向对象的静态强类型语言,声明并创建对象的代码很常见,根据某个类声明一个引用变量指向被创建的对象,并使用此引用变量操作改对象.

5、垃圾回收

java会对内存进行自动分配与回收管理,使上层业务更加安全,方便地使用内存实现现实逻辑.在不同的jvm实现及不同的回收机制中,堆内存的划分是不一样的.这里简要介绍回收(Garbage Collection ,GC).垃圾回收的主要目的是清除不用使用的对象,自动释放内存.

GC是如何判断对象是否可以被回收的呢?为了判断对象是否存活,JVM引入了GC Roots.如果一个对象与GC Roots之间没有直接或间接的引用关系,比如某个失去引用的对象,或者两个互相环岛状循环引用的对象等,判决这些对象“死缓”,是可以被回收的.什么对象可以作为GC Roots呢?比如:类静态属性中引用的对象、常量引用的对象、虚拟机栈中引用的对象、本地方法栈中引用的对象等.

有了判断对象是否存活的标准后,在了解一下垃圾回收的相关算法.最基础的为“标记-清除算法”,改算法会从每个GC Roots出发,依次标记有引用关系的对象,最后将没有被标记的对象清除.但是这种算法会带来大量的空间碎片,导致需要分配一个较大连续空间时容易触发FGC.为了解决这个问题,由提出类“标记-整理算法”,该算法类似计算机的磁盘整理,首先会从GC Roots出发标记存活的对象,然后将存活对象整理到内存空间的一端,形成连续的已使用空间,最后把已使用空间之外的部分全部清除,这样就不会产生碎片的问题.“Mark-Copy”算法,为了能够并行地标记和整理将空间分为两块,每次只激活一块,垃圾回收时只需把存活的对象复制到另外一块未激活空间上,将未激活空间标记为已激活,将已激活空间标记为未激活,然后清除原空间中的对象.堆内存空间分为较大的Eden和两块较小的Survivor,每次只使用Eden和Survivor区的一块.这种情形下的“Mark-Copy”减少了内存空间的浪费.“Mark-Copy”现作为主流的YGC算法进行新生代的垃圾回收.

垃圾回收器(Garbage Collector)是实现垃圾回收算法并应用在JVM环境中的内存管理模块.当前实现的垃圾回收器有数十种,如Serial回收器、CMS回收器、G1等.

cmu15445(2024fall) project 2 project 2比p1难度要更大,代码量更大且涉及的知识更多,实现中出现的bug更多,好在是最后全部解决了。我最大的收获在于对于多线程编程的理解更深入了,实际发现解决了多个多线程相关的bug,学会了更多多线程下debug的技巧方法,也见识了更多多线程的bug情况。在之后可以更系统的学习一下多线程编程。同时学会实现B+树也是需要掌握的基础。 阅读详情

相关推荐

金蝶ERP元数据解析:字段属性与表结构映射实战

本文深入解析金蝶ERP元数据的核心价值与应用实践,详细介绍了字段属性与表结构映射的关键技术。通过缓存获取与工具类直连两种方案对比,结合实际案例展示元数据在数据库校验、动态表单生成等场景的应用,帮助开发者高效解决二次开发中的常见问题。

weixin_33738555的博客 433

走进JVM--字节码

字节码 Java所有的指令有200个作用,一个字节(8位) 可以存储256种不同的指令信息,一个这样的字节称为字节码(Bytecode). 在代码的执行过程中,JVM 量字节码解释执行,屏蔽对底层操作系统的依赖; JVM 也可以将字节码编译执行,如果是热点代码,会通过JIT 动态地编译为机器码,提高执行效率. 如图所示:十六进制表示的二进制流通常是一个操作指令.起始的4个字节非常特殊,即绿色框的 cafe babe (十六进制) 是 Gosling 定义的一个魔法数,意思是Coffee Baby, 它的作

weixin_47081743的博客 382

基于Q-learning的无人机三维路径规划(含完整C++代码)

基于Q-learning的无人机三维路径规划(含完整C++代码)

weixin_54186646的博客 1万+

JAVA程序的执行【JVM,JDK,JRE】

JAVA代码的执行 Java源码 在Java编译器中 经过一系列的加工称.classs文件。 将.class文件放置到java虚拟机【JVM】。 Java续集你使用类加载器加载class文件。 类加载器加载完成之后,对字节码进行校验,字节码校验通过后JVM吧字节码翻译成机器码交给操作系统执行。 Java编译器 .java源码 在Java编译器中【词法分析、语法分析、语义分析、字节码生成器】...

chen_yeye的博客 276

Synopsys的CoreConsultant使用简析

CoreConsultant使用简析

weixin_58165606的博客 1万+

Python+whisper/vosk实现语音识别

Whisper 是一个由 OpenAI 开发的人工智能语音识别模型,它能够将语音转换为文本。Whisper 模型特别之处在于它的设计目标是能够理解和转录多种语言的语音,包括但不限于英语。Whisper 模型在训练时使用了大量不同语言的语音数据,这使得它具有很好的跨语言能力。Vosk 是一个开源的语音识别库,它可以在离线环境下工作,不依赖于任何外部服务。Vosk 基于Kaldi语音识别框架,支持多种语言,包括中文。Vosk提供了多种预训练模型,可以根据需求选择适合的模型进行语音识别。

weixin_44458771的博客 5942

Java 类加载:字节码加载到Jvm中

前言 生成字节码后,这些数据如何加载到jsm中,并怎么存储成为了问题,本文主要研究一下这个内容。 加载到jvm 内存中 通过javac 转换成.class 字节码文件,这个时候计算机还是不能直接识别的,由jvm加载class文件,JVM的类加载是通过ClassLoader及其子类来完成的,再翻译成二进制指令,Java字节码的执行是由JVM解释器引擎来完成,类的层次关系和加载顺序可以由下图来描述: ...

笔记小屋 3174

泛微OA与金蝶云星空审批流程对接实战:从报销单到采购合同的完整指南

本文详细介绍了泛微OA与金蝶云星空审批流程的深度集成方案,涵盖从报销单到采购合同的完整对接指南。通过API层面的无缝连接,实现流程自动化、数据同源和权限联动,显著提升企业业务效率。文章还提供了环境配置、数据映射、接口安全等实用技巧,助力企业轻松完成系统对接。

weixin_29268637的博客 245

JVM常见问题总结

JVM内存结构布局 JVM内存主要分为:本地方法栈、虚拟机栈、程序计数器、堆、方法区、元空间 堆(参考7. Java内存回收机制) OOM故障发源地,存放着几乎所有的实例对象,由GC自动进行垃圾回收,线程间资源共享,可以通过参数进行手动调节。但是线上环境应将-Xms和-Xmx设置成相等的值,避免堆空间频繁缩容与扩容带来的性能损耗。堆内存模型 元空间 Java8之后使用元空间替换原来的永久代...

sinat_33755317的博客 620

Python 爬虫实战:爬取国家统计局公开数据

国家统计局作为权威的宏观经济数据发布机构,汇聚了人口、GDP、就业、产业经济等多维度的核心统计数据,是开展经济研究、政策分析、行业洞察的重要数据支撑。相较于商业数据平台,国家统计局的公开数据具备权威性、全面性和时效性等特点,但部分数据分散在不同栏目且缺乏结构化下载渠道。本文基于 Python 爬虫技术,系统讲解国家统计局公开数据的爬取方法,重点解决静态表格解析、分页数据抓取、数据结构化转换等问题,同时严格遵循政府网站数据使用规范,为科研、教学等场景提供合规的数据获取方案。本文以国家统计局官网(

2503_91057718的博客 1819

高云FPGA系列教程(8):ARM串口数据接收(中断和轮询方式)

GW1NSR-4C ARM部分共有2个串口外设,都挂载在APB1总线上,最高支持波特率921.6Kbit/s,无奇偶校验位,8位数据位,1位停止位,支持高速测试模式 HSTM(High Speed Test Mode),即每个时钟周期输出1位数据,可以在短时间内传输大量数据。官方手册上没有描述发送和接收缓存FIFO的深度,所以不确定是否支持缓存。

whik1194的博客 1685

走进JVM

1.JVM简介 1.1JVM概念 虚拟机简介:JVM(Java Virtual Machine的简称。Java虚拟机。),JVM是一台被定制过的现实中不存在的计算机。 虚拟机:指通过软件模拟的完整的硬件环境功能的、运行在一个完全隔离的环境中的完整计算机系统。 常见虚拟机:JVM、VMwave、Virtual Box JVM和其他两个虚拟机的区别: a.VMwave与VirtualBox...

yunhyoung的博客 238

端侧 AI 落地避坑指南(中):为什么 QAT 救不了精度?——对齐“融合后算子“的硬件物理约束

在上一篇文章中,我们深入探讨了量化的本质,并得出结论:QAT(量化感知训练)是保持精度的关键。明明做了 QAT,精度还是崩塌了!让我们看一个真实的案例:✅ 使用了✅ 配置了量化✅ 训练了 50 个 epoch,学习率降为原来的 1/10✅ 冻结了 BN 统计量FP32 模型:mAP = 0.85QAT 后 FP32:mAP = 0.84(正常)工具量化后:mAP = 0.68(崩塌!问题出在哪里?层融合(Layer Fusion)机制。

weixin_51988935的博客 55

JVM_Java虚拟机<深入理解Java虚拟机>走进JVM

由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令。时至今日,尽管嵌入式平台已经不是Java程序的主流运行平台了(准确来说应该是HotSpotVM的宿主环境已经不局限于嵌入式平台了),那么为什么不将架构更换为基于寄存器的架构呢?栈:跨平台性、指令集小、指令多、执行性能比寄存器差言包括:Java、Scala、Groovy、Kotlin;

Coastlise的博客 1168

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

浅谈JVM,走进JVM的世界

走进JVM的世界,重新认识JVM ----->>>>>>>>原来JVM的世界我也懂 JVM有2种运行模式,一个是server,一个是client,client启动较快,而server模式启动启动较慢,但能长期稳定运行,运行之后会比client的速度快,我们常用的也是server模式,如何查看使用的是什么模式 很简单 java -version 就清楚了。 目录 1.什么是JVM 2.什么是class文件,被编译后的class字节码你还...

MWCSD的专栏 358

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

JVM笔记(一)走进JVM

走进JVM JVM相对于Java应用层的学习难度更大,**开篇推荐掌握的预备知识:**C/C++(关键)、微机原理与接口技术、计算机组成原理、操作系统、数据结构与算法、编译原理(不推荐刚学完JavaSE的同学学习),如果没有掌握推荐的一半以上的预备知识,可能学习起来会比较吃力。 **本套课程中需要用到的开发工具:**CLion、IDEA、Jetbrains Gateway 此阶段,我们需要深入探讨Java的底层执行原理,了解Java程序运行的本质。开始之前,推荐各位都入手一本《深入理解Java虚拟机 第三版

qq_25928447的博客 3680

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

JVM-----第一章 走进Java

第一章 走进Java 都学到JVM了,还啥可走进的,下面的内容看我的其他博客.

Benjalin_76_84的博客 219

故事:走进JVM的世界(图文并茂)

注意!本文较长,建议先收藏再阅读。更多文章可以关注作者公众号:码上实战 你也可以 star 我的 GitHub上本文所属仓库:https://github.com/flyhero/MarkNote 说明:本文在 Java 8 Hotspot 64位操作系统下构思 小强是一个工作3年有余的开发工程师,从他的发量你就可以知道,小强资历还尚浅。 最近公司没什么事,他也开始无聊起来了...

weixin_29587979的博客 1117

走进 JVM —— ClassLoader

目录 ClassLoader JVM 的双亲委托机制 自定义 ClassLoader 破坏双亲模式例子——先从底层ClassLoader加载 重写 findClass 方法: 加载 class文件到内存 重写 loadClass 方法:破坏双亲委托 编写测试: 运行结果: 热部署: 参考资料: ClassLoader ClassLoader是一个抽象类,...

掉了根毛的博客 411

快来走进JVM吧

深入理解JVM 每个使用Java的开发者都知道Java字节码是在JRE中运行(JRE: Java 运行时环境)。JVM则是JRE中的核心组成部分,承担分析和执行Java字节码的工作,而Java程序员通常并不需要深入了解JVM运行情况就可以开发出大型应用和类库。尽管如此,如果你对JVM有足够了解,就会对Java有更好的掌握,并且能解决一些看起来简单但又尚未解决的问题。 所以,在本篇文章中,我将会介绍JVM工作原理,内部结构,Java字节码的执行及指令的执行顺序,并会介绍一些常见的JVM错误及其解决方案

极客云曦前端 220
上一篇: Java面试含答案(最全版)
下一篇: Mybatis Mapper接口实现类的源码分析
一尾鲫鱼
博客等级 码龄9年 7粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值