InsideJVM(3)--Methodarea(方法区)

http://www.594k.com/java/html/y2007m2/12122/

方法区
在一个jvm实例的内部,类型信息被存储在一个称为方法区的内存
逻辑区中。类型信息是由类加载器在类加载时从类文件中提取出来
的。类(静态)变量也存储在方法区中。

jvm实现的设计者决定了类型信息的内部表现形式。如,多字节变量
在类文件是以big-endian存储的,但在加载到方法区后,其存放
形式由jvm根据不同的平台来具体定义。

jvm在运行应用时要大量使用存储在方法区中的类型信息。在类型信息
的表示上,设计者除了要尽可能提高应用的运行效率外,还要考虑空间
问题。根据不同的需求,jvm的实现者可以在时间和空间上追求一种平
衡。

因为方法区是被所有线程共享的,所以必须考虑数据的线程安全。假如
两个线程都在试图找lava的类,在lava类还没有被加载的情况下,只
应该有一个线程去加载,而另一个线程等待。

方法区的大小不必是固定的,jvm可以根据应用的需要动态调整。同样
方法区也不必是连续的。方法区可以在堆(甚至是虚拟机自己的堆)中
分配。jvm可以允许用户和程序指定方法区的初始大小,最小和最大尺
寸。

方法区同样存在垃圾收集,因为通过用户定义的类加载器可以动态
扩展java程序,一些类也会成为垃圾。jvm可以回收一个未被引用
类所占的空间,以使方法区的空间最小。

类型信息
对每个加载的类型,jvm必须在方法区中存储以下类型信息:
一 这个类型的完整有效名
二 这个类型直接父类的完整有效名(除非这个类型是interface或是
    java.lang.Object,两种情况下都没有父类)
三 这个类型的修饰符(public,abstract, final的某个子集)
四 这个类型直接接口的一个有序列表

类型名称在java类文件和jvm中都以完整有效名出现。在java
源代码中,完整有效名由类的所属包名称加一个".",再加上类名
组成。例如,类Object的所属包为java.lang,那它的完整
名称为java.lang.Object,但在类文件里,所有的"."都被
斜杠“/”代替,就成为java/lang/Object。完整有效名在
方法区中的表示根据不同的实现而不同。

除了以上的基本信息外,jvm还要为每个类型保存以下信息:
 类型的常量池( constant pool)
 域(Field)信息
 方法(Method)信息
 除了常量外的所有静态(static)变量

常量池
jvm为每个已加载的类型都维护一个常量池。常量池就是这个
类型用到的常量的一个有序集合,包括实际的常量(string,
integer, 和floating point常量)和对类型,域和方法
的符号引用。池中的数据项象数组项一样,是通过索引访问的。
因为常量池存储了一个类型所使用到的所有类型,域和方法的
符号引用,所以它在java程序的动态链接中起了核心的作用。

域信息
jvm必须在方法区中保存类型的所有域的相关信息以及域的声明顺序,
域的相关信息包括:
域名
域类型
域修饰符(public, private, protected,static,final
        volatile, transient的某个子集)
       
方法信息
jvm必须保存所有方法的以下信息,同样域信息一样包括声明顺序
方法名
方法的返回类型(或 void)
方法参数的数量和类型(有序的)
方法的修饰符(public, private, protected, static, final,
           synchronized, native, abstract的一个子集)
除了abstract和native方法外,其他方法还有保存
方法的字节码(bytecodes)
操作数栈和方法栈帧的局部变量区的大小           
异常表

类变量(
  Class Variables
  译者:就是类的静态变量,它只与类相关,所以称为类变量
)
类变量被类的所有实例共享,即使没有类实例时你也可以访问它。
这些变量只与类相关,所以在方法区中,它们成为类数据在逻辑上
的一部分。在jvm使用一个类之前,它必须在方法区中为每个
non-final类变量分配空间。

常量(被声明为final的类变量)的处理方法则不同,每个常量都
会在常量池中有一个拷贝。non-final类变量被存储在声明它的
类信息内,而final类被存储在所有使用它的类信息内。

对类加载器的引用
jvm必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。
如果一个类型是由用户类加载器加载的,那么jvm会将这个类加载器的
一个引用作为类型信息的一部分保存在方法区中。

jvm在动态链接的时候需要这个信息。当解析一个类型到另一个类型的引用
的时候,jvm需要保证这两个类型的类加载器是相同的。这对jvm区分
名字空间的方式是至关重要的。

对Class类的引用
jvm为每个加载的类型(译者:包括类和接口)都创建一个
java.lang.Class的实例。而jvm必须以某种方式把
Class的这个实例和存储在方法区中的类型数据联系起来。

你可以通过Class类的一个静态方法得到这个实例的引用
// A method declared in class java.lang.Class:
public static Class forName(String className);

假如你调用forName("java.lang.Object"),你会得到与
java.lang.Object对应的类对象。你甚至可以通过这个函数
得到任何包中的任何已加载的类引用,只要这个类能够被加载
到当前的名字空间。如果jvm不能把类加载到当前名字空间,
forName就会抛出ClassNotFoundException。
(译者:熟悉COM的朋友一定会想到,在COM中也有一个称为
      类对象(Class Object)的东东,这个类对象主要
      是实现一种工厂模式,而java由于有了jvm这个中间
      层,类对象可以很方便的提供更多的信息。这两种类对象
      都是Singleton的)

也可以通过任一对象的getClass()函数得到类对象的引用,
getClass被声明在Object类中:
// A method declared in class java.lang.Object:
public final Class getClass();
例如,假如你有一个java.lang.Integer的对象引用,可以
激活getClass()得到对应的类引用。

通过类对象的引用,你可以在运行中获得相应类存储在方法区
中的类型信息,下面是一些Class类提供的方法:
// Some of the methods declared in class java.lang.Class:
public String getName();
public Class getSuperClass();
public boolean isInterface();
public Class[] getInterfaces();
public ClassLoader getClassLoader();

这些方法仅能返回已加载类的信息。getName()返回类的完整名,
getSuperClass()返回父类的类对象,isInterface()判断
是否是接口。getInterfaces()返回一组类对象,每个类对象
对应一个直接父接口。如果没有,则返回一个长度为零的数组。
getClassLoader()返回类加载器的引用,如果是由启动类加载器
加载的则返回null。所有的这些信息都直接从方法区中获得。

方法表
为了提高访问效率,必须仔细的设计存储在方法区中的数据信息
结构。除了以上讨论的结构,jvm的实现者还可以添加一些其他的
数据结构,如方法表。jvm对每个加载的非虚拟类的类型信息中都
添加了一个方法表,方法表是一组对类实例方法的直接引用(包括
从父类继承的方法)。jvm可以通过方法表快速激活实例方法。
(译者:这里的方法表与C++中的虚拟函数表一样,但java方法全都
      是virtual的,自然也不用虚拟二字了。正像java宣称没有
      指针了,其实java里全是指针。更安全只是加了更完备的检查
      机制,但这都是以牺牲效率为代价的,个人认为java的设计者
      始终是把安全放在效率之上的,所有java才更适合于网络开发)

一个例子
为了显示jvm如何使用方法区中的信息,我们据一个例子,我们
看下面这个类:
class Lava {
    private int speed = 5; // 5 kilometers per hour
    void flow() {
    }
}

class Volcano {
    public static void main(String[] args) {
        Lava lava = new Lava();
        lava.flow();
    }
}
下面我们描述一下main()方法的第一条指令的字节码是如何被执行
的。不同的jvm实现的差别很大,这里只是其中之一。

为了运行这个程序,你以某种方式把“Volcano"传给了jvm。有了
这个名字,jvm找到了这个类文件(Volcano.class)并读入,它从
类文件提取了类型信息并放在了方法区中,通过解析存在方法区中的
字节码,jvm激活了main()方法,在执行时,jvm保持了一个指向当前
类(Volcano)常量池的指针。

注意jvm在还没有加载Lava类的时候就已经开始执行了。正像大多数的
jvm一样,不会等所有类都加载了以后才开始执行,它只会在需要的时候
才加载。

main()的第一条指令告知jvm为列在常量池第一项的类分配足够的内存。
jvm使用指向Volcano常量池的指针找到第一项,发现是一个对Lava类
的符号引用,然后它就检查方法区看lava是否已经被加载了。

这个符号引用仅仅是类lava的完整有效名”lava“。这里我们看到为了jvm
能尽快从一个名称找到一个类,一个良好的数据结构是多么重要。这里jvm
的实现者可以采用各种方法,如hash表,查找树等等。同样的算法可以用于
Class类的forName()的实现。

当jvm发现还没有加载过一个称为"Lava"的类,它就开始查找并加载类
文件"Lava.class"。它从类文件中抽取类型信息并放在了方法区中。

jvm于是以一个直接指向方法区lava类的指针替换了常量池第一项的符号
引用。以后就可以用这个指针快速的找到lava类了。而这个替换过程称为
常量池解析(constant pool resolution)。在这里我们替换的是一个
native指针。

jvm终于开始为新的lava对象分配空间了。这次,jvm仍然需要方法区中
的信息。它使用指向lava数据的指针(刚才指向volcano常量池第一项的指针)
找到一个lava对象究竟需要多少空间。

jvm总能够从存储在方法区中的类型信息知道某类型对象需要的空间。但一个
对象在不同的jvm中可能需要不同的空间,而且它的空间分布也是不同的。
(译者:这与在C++中,不同的编译器也有不同的对象模型是一个道理)

一旦jvm知道了一个Lava对象所要的空间,它就在堆上分配这个空间并把这个实例
的变量speed初始化为缺省值0。假如lava的父对象也有实例变量,则也会初始化。

当把新生成的lava对象的引用压到栈中,第一条指令也结束了。下面的指令利用这个
引用激活java代码把speed变量设为初始值,5。另外一条指令会用这个引用激活
Lava对象的flow()方法。

Revit模型转点云全流程:从OBJ导出到CloudCompare点云生成(2020版) 本文详细介绍了将Revit模型转换为点云数据的完整流程,特别针对Revit 2020用户。通过使用OBJ导出插件和开源软件CloudCompare,实现从模型导出、网格采样到生成结构化PCD点云的全过程,并提供了关键参数设置与常见问题解决方案,为BIM与三维数字孪生应用提供技术支持。 阅读详情

相关推荐

Verilog单周期CPU设计(超详细)

实验 单周期CPU一、设计目的与目标实验内容实验要求二、课程设计器材硬件平台软件平台三、 CPU逻辑设计总体方案指令模块MIPS指令格式指令处理流程数据通路总体结构图设计流程逻辑图四、模块详细设计PCAdd4PCINSTMEMDATAMEMSHIFTER32_L2SHIFTER_COMBINATIONMUX4X32MUX2X5EXT16T32MUX2X32CONUNITREGFILEALUSing...

Ace Cheney的博客 9万+

方法区(Method Area)详解

1. 方法区的基本理解 1.1 栈,堆和方法区的关系 方法区可以看作是独立于Java堆的一部分,并且也是和堆一样是整个JVM实例共用一份。 1.2 方法区的基本理解 各个线程共享区域 在JVM启动时被创建,并且物理内存可以不连续 大小可以固定也可以是动态扩展的 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类会出现OOM错误。 会随着JVM的关闭而释放这一区域的内存 1.3 方法去的演进 在JDK 7以前,习惯上把方法区称为永久代(习惯上),而到了JDK8,终于..

qq_43684005的博客 1万+

从零到一:手把手教你用Python搭建医学影像识别CNN模型(附完整代码)

本文详细介绍了如何使用Python和TensorFlow/Keras从零开始构建一个医学影像识别的CNN模型,涵盖数据预处理、模型架构设计、训练调优及部署全流程。通过实战案例和完整代码,帮助开发者快速掌握深度学习在医学影像识别中的应用,特别适合医疗AI领域的初学者和研究者。

spark7igniter的博客 200

JVM(五):运行时数据区 方法区 详解

JVM(四):运行时数据区 方法区 详解栈、堆、方法区数据交互关系概念方法区的演进方法区的大小(JDK8) 栈、堆、方法区数据交互关系 从内存分配角度来看 从线程共享与否角度来看 概念 《Java虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择区进行来及收集或者进行压缩。”但对于HotSpot JVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。所以,方法区看做是一块独立于Java堆的内存空间。 方法区(Method Are

World哥 781

用74LS160和74LS194搭个复古流水灯:从Multisim仿真到面包板实战(附完整电路图)

本文详细介绍了如何使用74LS160和74LS194芯片搭建复古流水灯电路,从Multisim仿真到面包板实战的全过程。通过解析核心器件特性、提供完整材料清单、仿真验证电路逻辑,以及实际搭建中的布局规划和调试技巧,帮助电子爱好者掌握这一经典数字电路设计项目。

weixin_28736355的博客 388

AFSim 2.9实战指南:从入门到精通的中文教程

本文是AFSim 2.9的实战指南,提供从零开始的中文教程。内容涵盖仿真环境搭建、实体行为控制、脚本编写,到传感器、武器系统集成与复杂想定构建,最后讲解数据记录与结果分析方法,帮助用户快速掌握这一强大的军事仿真框架。

weixin_29281941的博客 943

方法区(Method Area)

表中,曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存。《Java虚拟机规范》对方法区的约束是非常宽松的,除了和Java堆一样不需要连续的内存和可以选。其是类型的卸载,条件相当苛刻,但是这部分区域的回收有时又确实是必要的。的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收效果比较难令人满意,尤。根据《Java虚拟机规范》的规定,如果方法区无法满足新的内存分配需求时,将抛出。

weixin_41812346的博客 384

Procedural modeling

What is procedural modeling? One content generation option is modeling buildings, plants, clouds, cities, and worlds using an underlying system of rules. 1 Procedural Modeling: Grammars A rule-based generative system loosely organized as: ...

qq_24505417的博客 711

JVM内存区域-方法区(Method Area)

在 Java 虚拟机(JVM)中,内存区域是 JVM 运行时对 Java 程序进行管理的重要机制。JVM 将其运行时内存划分为多个区域,其中包括堆(Heap)、虚拟机栈(Stack)、本地方法栈(Native Method Stack)、程序计数器(Program Counter Register)和方法区(Method Area)。方法区是 JVM 运行时数据区域的一部分,用来存储每个类的信息。它在 JVM 启动时被创建,属于所有线程共享的内存区域。

Flying_Fish_roe的博客 1160

保姆级教程:用YOLOv5+ROS2 Humble搞定奥比中光Dabai DCW深度相机的3D物体定位

本教程详细介绍了如何使用YOLOv5模型和ROS2 Humble系统,结合奥比中光Dabai DCW深度相机实现3D物体定位。从环境配置、模型部署到深度数据融合,提供完整的实战指南,帮助开发者快速掌握三维坐标提取技术,适用于机器人开发和计算机视觉应用。

weixin_26765363的博客 270

EMGPro 肌肉电手势识别手环传感器

EMG手势识别技术需要进行多方面的工作,包括传感器的设计和布局、EMG信号的采集和预处理、特征提取和分类等。通过对采集到的信号进行特征提取和分类,可以将手势信号与预定义的手势模型进行匹配,从而实现手势识别和控制。通过使用EMG手势识别技术,用户可以更加自由地操纵设备,使得我们的交互方式更加智能和自然。EMG手势识别是利用EMG信号测量肌肉运动的实时性和高精度性,采用机器学习等技术进行数据处理和分析,并将其应用于手势识别领域的一种技术。

m0_68593468的博客 1385

JVM 方法区(Method Area)

JVM 方法区 文章目录JVM 方法区方法区的理解栈、堆、方法区的交互关系HotSpot中方法区的演进永久代为什么要使用元空间替换字符串常量池(StringTable)为什么要调整方法区的内部结构类型信息域(Field)信息方法(Method)信息代码举例non-final 类型的类变量全局常量 static final运行时常量池解释常量池和运行时常量池方法区的垃圾回收类卸载常见面试题 方法区的理解 运行时数据区: 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已

TheAnnoyingDog的博客 3859

Open3D——点云构建Delaunay三角网【2026最新版】

点云构建Delaunay三角网

点云侠的博客 8367

Method Area(方法区)

方法区是各个线程共享的内存区域,在虚拟机启动时创建。 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却又一个别名叫做Non-Heap(非堆),目的是与Java堆区分开来。 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。 The Java Virtual Machine has a method area that is shared among all Java Virtual

Leon_Jinhai_Sun的博客 272

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

不可不知的JVM 中堆 Heap、栈 Stack、方法区 Method area 、本地方法区 Native method area

每个jvm实例都有方法区和一个堆(hasone method area and one heap)。这两个区域被jvm中的线程共享。当JVM加载了一个class文件后,则class中的参数、类型等信息会存储在方法区中。程序运行时所有创建的对象存储在堆中。          当每一个新线程启动时会有自己的程序计数器pcregister (program counter)和栈,如果线程调用方法,则程

Jerryai1的专栏 2596

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

内存中的栈(stack)、堆(heap)和方法区(method area)的用法

(1)定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间; (2)通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured;

m0_37718872的博客 4066

JVM-011-方法区(Method Area)

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。 对于习惯在HotSpot虚拟机上开发、部署程序的开发者来说,很多人都更愿意把方法区称为“永久代”(Per...

qq_33605778的博客 358

JVM学习笔记-方法区(Method Area)

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。 对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久...

denverj的专栏 352

Java方法区、栈及堆

Java方法区、栈及堆一 方法区(Method Area)1. 什么是方法区(Method Area)?《深入理解JVM》书中对方法区(Method Area)描述如下: 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。 2.方法区(Method Area)存储什么?《深入理解JVM》书中对方法区(Method Area)存储内容描述如下: 它存储已被Java虚拟

蜗牛 1万+

JVM中的方法区(Method Area)(转载/整理)

Java在内存中专门划分出一块静态存储区域(即在固定位置上存放应用程序运行时一直存在的数据,由于位置固定,下次调用时便省去了查找的麻烦),称为方法区。 类型信息(这里的类型指类或接口)是由类加载器在类加载时从类文件中提取出来的,被存储在方法区。另外,类(静态)变量也存储在方法区中。JVM在运行应用时要大量使用存储在方法区中的类型信息。在类型信息的表示上,设计者除了要尽可能...

weixin_33974433的博客 294

方法区(Method Area)存储的方法(Method)

程序运行时会加载类编译生成的字节码,这个过程中静态变量(类变量)和静态方法及普通方法对应的字节码加载到方法区。 但是!!!方法区中没有实例变量,这是因为,类加载先于对应类对象的产生,而实例变量是和对象关联在一起的,没有对象就不存在实例变量,类加载时没有对象,所以方法区中没有实例变量 静态变量(类变量)和静态方法及普通方法在方法区(Method Area)存储方式是有区别的 ...

luzhensmart的专栏 411

解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法

        通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured;...

lcx390549721的博客 1922

运行时数据区域——方法区(Method Area)。

博文中的内容来源《深入理解Java虚拟机_JVM高级特性与最佳实践》这一本书,感激不尽。

孤芳不自赏 1368

Coding Agent 实践指南:IDE 插件、云端 IDE 与结对编程

在人工智能辅助开发领域,Coding Agent 正从单纯的代码补全工具演变为深度嵌入研发流程的智能协作者。其核心原理基于大语言模型与工具调用循环,通过上下文收集、自主修改、测试执行等能力,实现从需求理解到代码落地的自动化闭环。这种技术价值不仅体现在提升个人编码效率,更在于推动团队协作模式的变革,尤其适合重构、测试补全、模式化迁移等标准化任务。随着云端 IDE 的兴起,Agent 得以在隔离的沙箱环境中长时运行,开发者可异步提交任务并审阅生成的 PR,有效解决本地计算资源受限与任务中断问题。而结对编程的新范

ciya3282的博客 431

Java的永久代和元空间及各种常量池

转载地址:https://www.cnblogs.com/jwcz/p/11772143.html 永久代 Java 的内存中有一块称之为方法区的部分,在 JDK8 之前, Hotspot 虚拟机中的实现方式为永久代(Permanent Generation),别的JVM都没有这个东西。 在过去(当自定义类加载器使用不普遍的时候),类几乎是“静态的”并且很少被卸载和回收,因此类也可以被看成“...

Lizhj的博客 1819

一起学习JVM-内存结构-方法区(Method Area)(线程共享的区域)

文章目录方法区(Method Area) 方法区(Method Area) 定义: 存储了跟类相关的信息,如:成员变量、方法、构造器及常量池等。 逻辑上是堆的一部分,但是具体的实现是不一样的。比如:oracle公司的Hotspot JVM 在1.8之前方法区的实现叫永久代,就是使用堆的一部分作为方法区。 而1.8之后方法区的实现叫元空间,使用的是本地内存也就是系统内存。 特点: 1.所有Ja...

凹凸曼的博客 821

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

weixin_44218929的博客 166
上一篇: Active Directory 结构白皮书
下一篇: ofbiz直接调用jdbc
topinking
博客等级 码龄20年 15粉丝 242原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值