Java程序员深入java虚拟机(二)——类的生命周期(上)类的加载和连接

Java虚拟机类加载机制探究:生命周期、初始化、使用与验证 深度解析Java虚拟机中类的生命周期,包括加载、验证、初始化等阶段。强调主动和被动使用触发条件,总结类加载器类型和获取方法。 阅读详情
  本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.youkuaiyun.com/csh624366188     

         类加载器,顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。基本上所有的类加载器都是 java.lang.ClassLoader类的一个实例。其实我们研究类加载器主要研究的就是类的生命周期


      首先来了解一下jvm(java虚拟机)中的几个比较重要的内存区域,这几个区域在java类的生命周期中扮演着比较重要的角色:


方法区:在java的虚拟机中有一块专门用来存放已经加载的类信息、常量、静态变量以及方法代码的内存区域,叫做方法区。


常量池:常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信息。


堆区:用于存放类的对象实例。


栈区:也叫java虚拟机栈,是由一个一个的栈帧组成的后进先出的栈式结构,栈桢中存放方法运行时产生的局部变量、方法出口等信息。当调用一个方法时,虚拟机栈中就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失,如果方法中调用了其他方法,则继续在栈顶创建新的栈桢。

类的生命周期
        当我们编写一个java的源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到卸载的全过程。一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况,这里我们主要来研究类加载器所执行的部分,也就是加载,链接和初始化。如图所示:
                  

下面我先简单看一下类加载器所执行的三部分的简单介绍
1、加载:查找并加载类的二进制数据 

2、连接 

    –验证:确保被加载的类的正确性 

    –准备:为类的静态变量分配内存,并将其初始化为默认值 

    –解析:把类中的符号引用转换为直接引用 

3、初始化:为类的静态变量赋予正确的初始值 

     从上边我们可以看出类的静态变量赋了两回值。这是为什么呢?原因是,在连接过程中时为静态变量赋值为默认值,也就是说,只要是你定义了静态变量,不管你开始给没给它设置,我系统都为他初始化一个默认值。到了初始化过程,系统就检查是否用户定义静态变量时有没有给设置初始化值,如果有就把静态变量设置为用户自己设置的初始化值,如果没有还是让静态变量为初始化值

类的加载、连接和初始化


类的加载

     类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 。这里的class对象其实就像一面镜子一样,外面是类的源程序,里面是class对象,它实时的反应了类的数据结构和信息。

加载.class文件的方式 

1、从本地系统中直接加载 

2、通过网络下载.class文件 

3、从zip,jar等归档文件中加载.class文件 

4、从专有数据库中提取.class文件 

5、将Java源文件动态编译为.class文件 

类的加载过程

结论:

1、类的加载的最终产品是位于堆区中的Class对象 

2、Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口 

Java虚拟机给我们提供了两种类加载器:

1、Java虚拟机自带的加载器 

1)根类加载器(使用C++编写,程序员无法在Java代码中获得该类) 

2)扩展加载器,使用Java代码实现 

3)系统加载器(应用加载器),使用Java代码实现 

2、用户自定义的类加载器 

     java.lang.ClassLoader的子类 

     用户可以定制类的加载方式 


我们看一下API对ClassLoader的介绍:

   类加载器是负责加载类的对象。ClassLoader 类是一个抽象类。如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。每个class对象都包含一个对定义它的 ClassLoader 的引用。

我们再来看一下Class类的一个方法getClassLoader

public ClassLoader getClassLoader()

返回该类的类加载器。有些实现可能使用 null 来表示根类加载器。如果该类由根类加载器加载,则此方法在这类实现中将返回 null。 


下面我们来看一个小例子来验证一下:

[java] view plain copy
  1. package com.bzu.csh;  
  2. public class Test  
  3. {  
  4. public static void main(String[] args) throws Exception  
  5. {  
  6. Class clazz = Class.forName("java.lang.String");  
  7. System.out.println(clazz.getClassLoader());  
  8. Class clazz2 = Class.forName("com.bzu.csh.ABC");  
  9. System.out.println(clazz2.getClassLoader());  
  10. }  
  11. }  
  12. class ABC  
  13. {  
  14. }  


看一下打印结果,一目了然:


从上面打印结果可以看出,第一个为null,也就是它用根类加载器加载的,第二个是我们自己写的类,也就是说,我们自己写的那个类用sun.misc.Launcher$AppClassLoader@1372a1a加载器加载的,我们可以看到APP,也就是应用类加载器,也就是系统加载器


还记得我们以前用过的动态代理吧,InvocationHandler,当我们利用proxy对象调用newProxyInstance建立一个代理类时,我们要给他传一个ClassLoader,也就是类加载器,如下:

[java] view plain copy
  1. public static Object newProxyInstance(ClassLoader loader,  
  2.                                       Class<?>[] interfaces,  
  3.                                       InvocationHandler h)  
  4.                                throws IllegalArgumentException  


        当时我们学习的时候,只知道这里的loader随便给他设置一个类的类加载器就可以。现在我们来想想为什么这里需要一个类加载器呢?我们知道这个newProxyInstance是动态的给我们生成一个代理类,然后根据这个代理类生成一个代理对象。动态生成这个代理类之后我们不得把他加载到内存里吗,加载到内存里我们才可以用他。用什么加载到内存里,只有类加载器,所以我们要给他指定一个类加载器。


      类加载器并不需要等到某个类被“首次主动使用”时再加载它 。JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到了.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(LinkageError错误) 如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误 。大家在做web开发的时候有可能会出现这种问题,比如我们在做测试的时候是用的jdk1.6,而我们在部署的时候我们用的是jdk1.5.这时候就很可能汇报LinkageError错误,版本不兼容。


类的连接

类被加载后,就进入连接阶段。连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去。 

验证:当一个类被加载之后,必须要验证一下这个类是否合法,比如这个类是不是符合字节码的格式、变量与方法是不是有重复、数据类型是不是有效、继承与实现是否合乎标准等等。总之,这个阶段的目的就是保证加载的类是能够被jvm所运行。很多人都感觉,既然这个类都通过编译加载到内存里了,那肯定就是合法的了,为什么还要验证呢,这是因为这里的验证时为了避免有人恶意编写class文件,也就是说并不是通过编译得到的class文件。所以这里验证其实是检查的class文件的内部结构是否符合字节码的要求


准备:准备阶段的工作就是为类的静态变量分配内存并设为jvm默认的初值,对于非静态的变量,则不会为它们分配内存。有一点需要注意,这时候,静态变量的初值为jvm默认的初值,而不是我们在程序中设定的初值。jvm默认的初值是这样的:
基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。
引用类型的默认值为null。
常量的默认值为我们程序中设定的值,比如我们在程序中定义final static int a = 100,则准备阶段中a的初值就是100。


解析:这一阶段的任务就是把常量池中的符号引用转换为直接引用。那么什么是符号引用,什么又是直接引用呢?我们来举个例子:我们要找一个人,我们现有的信息是这个人的身份证号是1234567890。只有这个信息我们显然找不到这个人,但是通过公安局的身份系统,我们输入1234567890这个号之后,就会得到它的全部信息:比如山东省滨州市滨城区18号张三,通过这个信息我们就能找到这个人了。这里,123456790就好比是一个符号引用,而山东省滨州市滨城区18号张三就是直接引用。在内存中也是一样,比如我们要在内存中找一个类里面的一个叫做show的方法,显然是找不到。但是在解析阶段,jvm就会把show这个名字转换为指向方法区的的一块内存地址,比如c17164,通过c17164就可以找到show这个方法具体分配在内存的哪一个区域了。这里show就是符号引用,而c17164就是直接引用。在解析阶段,jvm会将所有的类或接口名、字段名、方法名转换为具体的内存地址。 


下一篇内容继续讲解类加载器内容。。。。

参考文章:http://www.2cto.com/kf/201204/129386.html

Dify视觉模型节点避坑指南:我用Qwen2.5-VL做OCR识别时踩过的3个坑(及解决方案) 本文分享了使用Dify平台和Qwen2.5-VL视觉模型进行OCR票据识别时遇到的三个常见问题及解决方案,包括文件变量传递、结构化输出和条件分支判断失效。通过实战经验,帮助开发者优化多模态模型在财务自动化中的应用,提升OCR识别精度和效率。 阅读详情

相关推荐

基于计算机视觉的Windows自动化工具openclaw-win:从原理到实战

计算机视觉与自动化技术正深刻改变人机交互方式,其核心在于让机器具备“感知-决策-执行”的能力。通过图像采集与处理算法,程序可以识别屏幕上的特定元素;结合模拟输入技术,便能自动执行点击、拖拽等操作,形成完整的自动化闭环。这一技术栈在软件测试、数据采集、重复性办公任务等领域具有重要价值,能够显著提升工作效率。开源项目openclaw-win正是这一理念的工程实践,它整合了图像识别与模拟操作模块,为开发者提供了一个研究自动化技术的具体样本。项目涉及模板匹配、坐标计算等关键技术点,并需处理屏幕适配、操作延迟等实际问

weixin_28745975的博客 328

京东C++开发工程师 2019校招卷总结

1.一台客户端有三百个客户与三百个客户端有三百个客户对服务器施压,有什么区别? 一个客户端,三百个用户 只有一个客户端,三百个用户肯定不能同时进行操作,假设每次一人操作客户端对服务器施压,服务器承受的压力小但持续时间长。所有用户在一个客户端上,不必考虑分布式管理的问题。一个客户端三百个用户会占用客户机更多的资源,而影响测试的结果。线程之间可能发生干扰,而产生一些异常。而三百个用户的数据都在同一客户端,连接数显著减少,意味着需要更大的带宽来传输这些数据 三百个客户端,三百个用户 假设三百个客户端同时进行操作对

goodgoodstudy___的博客 4665

开源项目 ruoyi-sso-oauth2(一)环境配置

Ruoyi若依实现单点登录SSO、oauth2认证

Xiaoweidumpb 9683

JVM(一)原理

一、java虚拟机的生命周期:   Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。程序开始执行时他才运行,程序结束时他就停止。你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机。 Java虚拟机总是开始于一个main()方法,这个方法必须是公有、返回void、直接受一个字符串数组。在程序执行时,你必须给Java虚拟机指明这个包换main()方法的类名。 Main()方法是程序的起点,他被执行的线程初始化为程序的初始线程。程序中其他的线程都由他来启动。

weixin_38987366的博客 637

微信小程序 - 解决微信支付报错 requestPayment:fail no permission 原因分析及排查处理(支付失败出错,无法唤起支付弹框面板,微信支付API报错请求付款:失败无权限)

微信小程序,微信支付,支付报错,errMsg: "requestPayment:fail no permission",支付失败,支付权限没问题,微信小程序支付报错,检查了appid正确依旧不行,微信小程序支付异常,苹果ios手机,安卓手机,开发者工具模拟器,最新解决教程,小程序wx.requestPayment报错/无响应,小程序支付 requestPaym,微信小程序认证,真机运行,小程序微信支付提示错误,微信小程序里使用微信支付错误提示,微信小程序支付异常,微信支付弹框拉不起来,小程序支付api,都检

🏆 前端领域优质创作者 1万+

基于深度学习的大豆病害检测识别系统:YOLOv10 + UI界面 + 数据集

YOLOv10是一种高效的目标检测算法,能够在保持高精度的同时,提供较快的检测速度。YOLOv10使用了改进的卷积神经网络架构,并在多个计算机视觉任务中表现出色。在本项目中,我们将使用YOLOv10进行大豆病害的检测和分类。本系统利用YOLOv10算法,实现了大豆病害的实时检测和分类。通过结合深度学习和图像处理技术,可以帮助农业领域的专业人员更加高效地识别和诊断大豆病害,提高农作物的生产力与质量。

YOLO 699

JVM基础:类的生命周期详解

类的生命周期描述了一个类加载、使用、卸载的整个过程。

siaok的博客 1652

机器学习实战5-天气预测系列:利用数据集可视化分析数据,并预测某个城市的天气情况

大家好,我是微学AI,最近天气真的是多变啊,忽冷忽热,今天再次给大家带来天气的话题,机器学习实战5-天气预测系列,我们将探讨一个城市的气象数据集,并利用机器学习来预测该城市的天气状况。该数据集包含年平均温度和湿度等信息。

微学AI的博客 1万+

Java类的生命周期(详细)

检验代码是否规范,ex:是否有覆盖final修饰的方法。比如对象的引用,数组名)读取class文件,在方法区保存该类的数据结构。对于“单入口”的过程结构程序,程序第一行就是第一条指令;整个类不再使用时,从方法区,堆中回收内存。,而程序都不知道从哪里执行,又如何执行创建实例的代码呢?对象的实体没有被引用,不再使用时,回收。在堆中分配实体,保存对象实体。记住:方法区存放的都是程序中永远唯一的元素。对类的字段,方法等进行转换。必须确定从哪个类的那个方法开始执行。堆区:保存数组实体,对象实体。

weixin_73373302的博客 796

30、电力生产系统中的效率测量

本文探讨了如何使用数据包络分析(DEA)模型来评估电力生产系统的效率。文章详细介绍了电力生产系统的三个主要环节——发电、输电和配电,并通过多种DEA模型,如输入导向模型、输出导向模型以及基于松弛的SBM模型,展示了效率测量的方法和技术。同时,结合实际案例分析,说明了DEA模型在识别效率低下环节及提出改进建议方面的应用价值。

rgv2345678的博客 116

SpringBoot中使用FastJson解析Json数据

场景 1.SpringBoot默认配置的是Jackson。 2.项目搭建专栏: https://blog.youkuaiyun.com/BADAO_LIUMANG_QIZHI/column/info/35688 实现 引入fastJson的依赖 <!-- fastjson的依赖 --> <dependency> <groupId>com.alibab...

BADAO_LIUMANG_QIZHI的博客 4140

【Java 基础篇】Java类加载器详解

Java允许开发人员自定义类加载器,以满足特定的加载需求。自定义类加载器必须继承类,并重写findClass方法。在findClass方法中,开发人员可以根据自己的规则和逻辑来加载类的字节码。// 根据名称加载类的字节码 byte [ ] byteCode = loadClassByteCode(name);// 调用defineClass方法将字节码转换为Class对象 return defineClass(name , byteCode , 0 , byteCode . length);

繁依Fanyi的博客 1万+

物联网设备数据是如何流转的:基于EMQX与TDengine的前后端分离项目实践

背景 在我写了TDengine极简实战:从采集到入库,从前端到后端,体验物联网设备数据流转这篇文章后,不少读者朋友评论、私信说可不可以提供代码参考学习下,那必须是可以的。那篇文章主要介绍了数据采集、数据传输、数据转发、数据解析、数据存储、数据查询、数据呈现、数据导出、消息推送的物联网设备数据流程过程,作为体验 TDengine 的极简实战项目,没引入过多的业务设计(复杂功能)以及异步解耦设计(消息中间件)。 在整理代码的过程中,我发现虽然整个项目并不复杂,但是涉及到的技术点较多,有必要对关键的组件进行说明

Heartsuit的博客 9412

Java程序员从笨鸟到菜鸟之(九十三)深入java虚拟机(二)——类的生命周期(上)类的加载和连接

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.youkuaiyun.com/csh624366188               类加载器,顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码

曹胜欢 2万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java程序员从笨鸟到菜鸟之(九十三)深入java虚拟机(二)——类的生命周期(上)类的加载和连接...

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.youkuaiyun.com/csh624366188 类加载器,顾名思义,类加载器(classloader)用来加载Java类到Java虚拟机中。一般来说,Java虚拟机使用Java类的方式如下:Java源程序(.java文件)在经过Java编译器编译之后就被转换成Java字节代码(.class文件)。类加载器负责...

红太阳照大地 272

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

(二)Java虚拟机——类的生命周期

类的生命周期描述了一个类从加载、使用、卸载的过程。类的生命周期有七个阶段其中连接阶段又可以细分为验证,准备,解析。

一位热爱编程的青年 1127

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java 入门指南:JVM(Java虚拟机)——类的生命周期与加载过程

类从被加载到虚拟机内存中开始到卸载出内存为止,它的整个生命周期可以简单概括为 7 个阶段:加载、验证、准备、解析、初始化、使用和卸载。其中,验证、准备和解析这三个阶段可以统称为连接。 的生命周期除去使用和卸载,就是 Java 的类加载过程。这 5 个阶段一般是顺序发生的,但在动态绑定的情况下,解析阶段发生在初始化阶段之后。系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。

热带鱼的技术博客 2183

深入理解Java虚拟机:Java类的加载机制

本篇内容包括:Java 类的加载机制(Jvm 结构组成、Java 类的加载)、类的生命周期(加载-验证-准备-解析-初始化-使用-卸载)、类加载器 以及 双亲委派模型。

栗筝i的博客 6122

java类的生命周期

在Java类的生命周期中,**加载阶段(Loading)**是类生命周期的第一个阶段,指的是JVM将类的字节码文件从外部(通常是硬盘或其他存储介质)加载到内存中的过程。加载阶段涉及到类加载器(ClassLoader)从类路径中找到相应的类文件,并将其加载到JVM内存中以便后续使用。请求加载:查找类文件:加载类字节码:创建类的对象:类加载器的作用非常重要,它负责从类路径中查找并加载类文件。在加载类时,JVM会根据类加载器的机制来决定如何加载不同的类。类加载器有几种类型,它们的职责如下:引导类加载器(Boots

gggfJJ的博客 1634

深入Java虚拟机之类加载

深入Java虚拟机_ClassLoader 类加载器深入剖析 Java虚拟机与程序的生命周期 在如下几种情况下,Java虚拟机将结束生命周期 执行了System.exit()方法程序正常执行结束程序在执行过程中遇到了异常或错误而异常终止由于操作系统出现错误而导致Java虚拟机进程 类的加载连接和初始化 加载:查找并加载类的二进制数据 连

前往JAVA架构的路上 3万+

Java中类的生命周期

Java虚拟机管理类和对象的生命周期; (1)类的生命周期从类被加载,连接,初始化开始,到类被卸载结束; (2)类处于生命周期时,它的二进制数据位于运行时方法区内,在堆区还有一个相应的描述类的Class类的对象; (3)只有当类处于生命周期中时,Java程序才能够使用它。   1.Java虚拟机及程序的生命周期 (1)通过java命令运行一个Java程序时,启动一个Java虚拟机进程;

JBuilder3的专栏 3862

深入java虚拟机(二)——类的生命周期(上)类的加载和连接

类加载器,顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 

u014654942的专栏 437

Java深度解析:类的生命周期与类加载过程

最近在学习Java 虚拟机,学到了类的声明周期,有些比较难理解的点,特地来总结一下。类的生命周期从大体上来看的话,有五个阶段,分别是加载,链接,初始化,使用,卸载。更细分的来看的话,有七个阶段,其实就是链接阶段又分为了验证、准备、解析。我们来详细的看看这几个阶段分别做了些什么。

无限进步的博客 1125

Java虚拟机(JVM)(6)—— 类的生命周期

本文主要介绍类的生命周期,以及在各阶段所执行的任务,希望对大家的日常工作有所帮助☺

知唔猪的博客 990

类的生命周期和类的加载

类的生命周期 一个类的完整生命周期如下: 加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的 解析阶段在某些情况下,可以在初始化阶段之后再开始 虚拟机规范规定,以下5种场景需要立即对类进行初始化工作 遇到特定字节码指令的时候 字节码指令:new、getstatic、putstatic、invokestatic 使用new关键字实例化对象 set/get类的静态字段(排除final修饰的字段) 调用类的静态方法 对类进行反射操作的时候 初始化一个类的时候,必

马丘 394
上一篇: Java程序员深入java虚拟机(一)——java虚拟机底层结构详解
下一篇: Java程序员深入java虚拟机(三)——类的生命周期(下)类的初始化
lmjsummer
博客等级 码龄9年 2粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值