jvm基础

面试题目:
地球人都知道,Java有个东西叫垃圾收集器,它让创建的对象不需要像c/cpp那样deletefree掉,你能不能谈谈:

GC是在什么时候,对什么东西,做了什么事情?

以上算是三个问题,下面逐一分析:

 

问题一回答:什么时候?
1.系统空闲的时候。
    分析:这种回答大约占30%,遇到的话一般我就会准备转向别的话题,譬如算法、譬如SSH看看能否发掘一些他擅长的其他方面。

2.
系统自身决定,不可预测的时间/调用System.gc()的时候。
    分析:这种回答大约占55%,大部分应届生都能回答到这个答案,起码不能算错误是吧,后续应当细分一下到底是语言表述导致答案太笼统,还是本身就只有这样一个模糊的认识。

3.能说出新生代、老年代结构,能提出minor gc/full gc
    分析:到了这个层次,基本上能说对GC运作有概念上的了解,譬如看过《深入JVM虚拟机》之类的。这部分不足10%

4.能说明minorgc/full gc的触发条件、OOM的触发条件,降低GC的调优的策略。
    分析:列举一些我期望的回答:eden满了minor gc,升到老年代的对象大于老年代剩余空间full gc,或者小于时被HandlePromotionFailure参数强制full gcgc与非gc时间耗时超过了GCTimeRatio的限制引发OOM,调优诸如通过NewRatio控制新生代老年代比例,通过 MaxTenuringThreshold控制进入老年前生存次数等……能回答道这个阶段就会给我带来比较高的期望了,当然面试的时候正常人都不会记得每个参数的拼写,我自己写这段话的时候也是翻过手册的。回答道这部分的小于2%

总结:程序员不能具体控制时间,系统在不可预测的时间调用System.gc()函数的时候;当然可以通过调优,NewRatio控制newObjectoldObject的比例,MaxTenuringThreshold 控制进入oldObject的次数,使得oldObject 存储空间延迟达到full gc,从而使得计时器引发gc时间延迟OOM的时间延迟,以延长对象生存期。

问题二回答:对什么东西
1.不使用的对象。
    分析:相当于没有回答,问题就是在问什么对象才是不使用的对象。大约占30%
2.超出作用域的对象/引用计数为空的对象。
    分析:这2个回答站了60%,相当高的比例,估计学校教java的时候老师就是这样教的。第一个回答没有解决我的疑问,gc到底怎么判断哪些对象在不在作用域的?至于引用计数来判断对象是否可收集的,我可以会补充一个下面这个例子让面试者分析一下obj1obj2是否会被GC掉?

classC{
         public Object x;
    }
    C obj1obj2 = new C();
    obj1.x = obj2;
    obj2.x = obj1;
    obj1obj2 = null;

3.
gc root开始搜索,搜索不到的对象。
    分析:根对象查找、标记已经算是不错了,小于5%的人可以回答道这步,估计是引用计数的方式太深入民心了。基本可以得到这个问题全部分数。
    PS:有面试者在这个问补充强引用、弱引用、软引用、幻影引用区别等,不是我想问的答案,但可以加分。

4.root搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。
    分析:我期待的答案。但是的确很少面试者会回答到这一点,所以在我心中回答道第3点我就给全部分数。 
总结:超出了作用域或引用计数为空的对象;从gc root开始搜索找不到的对象,而且经过一次标记、清理,仍然没有复活的对象。

 

问题三回答:做什么?
1.删除不使用的对象,腾出内存空间。
    分析:同问题2第一点。40%
2.补充一些诸如停止其他线程执行、运行finalize的说明。
    分析:起码把问题具体化了一些,如果像答案1那样我很难在回答中找到话题继续展开,大约占40%的人。
    补充一点题外话,面试时我最怕遇到的回答就是这个问题我说不上来,但是遇到的时候我上网搜一下能做出来。做程序开发确实不是去锻炼茴香豆的有几种写法,不死记硬背我同意,我不会纠语法、单词,但是多少你说个思路呀,要直接回答一个上网搜,我完全没办法从中获取可以评价应聘者的信息,也很难从回答中继续发掘话题展开讨论。建议大家尽量回答引向自己熟悉的,可讨论的领域,展现给面试官最擅长的一面。

3.能说出诸如新生代做的是复制清理、from survivortosurvivor是干啥用的、老年代做的是标记清理、标记清理后碎片要不要整理、复制清理和标记清理有有什么优劣势等。
    分析:也是看过《深入JVM虚拟机》的基本都能回答道这个程度,其实到这个程度我已经比较期待了。同样小于10%
4.除了3外,还能讲清楚串行、并行(整理/不整理碎片)、CMS等搜集器可作用的年代、特点、优劣势,并且能说明控制/调整收集器选择的方式。
    分析:同上面2个问题的第四点。 
总结:删除不使用的对象,回收内存空间;运行默认的finalize,当然程序员想立刻调用就用dipose调用以释放资源如文件句柄,JVMfrom survivorto survivor对它进行标记清理,对象序列化后也可以使它复活。
   千万不要说网上google下,就算说也要说出自己以前遇到这样的问题是怎么处理的,对这个知识有什么认识想法,然后可以反问下考官,这样可以不让技术型的考官为如何继续话题而对你无语,呵呵。

 JVM相关面试题及答案

原创 2017年03月20日 15:47:37

·        标签:

·        jvm /

·        面试题 /

·        答案

·        24246

题目: 
http://www.jsondream.com/2016/12/04/java-interview-question.html

答案如下:

1. 类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行顺序

答:先静态、先父后子。 
先静态:父静态 > 子静态 
优先级:父类 > 子类 静态代码块 > 非静态代码块 > 构造函数 
一个类的实例化过程: 
1,父类中的static代码块,当前类的static 
2,顺序执行父类的普通代码块 
3,父类的构造函数 
4,子类普通代码块 
5,子类(当前类)的构造函数,按顺序执行。 
6,子类方法的执行,

2. JVM内存分配

3. Java 8的内存分代改进

从永久代到元空间,在小范围自动扩展永生代避免溢出

4. JVM垃圾回收机制,何时触发MinorGC等操作

分代垃圾回收机制:不同的对象生命周期不同。把不同生命周期的对象放在不同代上,不同代上采用最合适它的垃圾回收方式进行回收。 
JVM中共划分为三个代:年轻代、年老代和持久代, 
年轻代:存放所有新生成的对象; 
年老代:在年轻代中经历了N次垃圾回收仍然存活的对象,将被放到年老代中,故都是一些生命周期较长的对象; 
持久代:用于存放静态文件,如Java类、方法等。 
新生代的垃圾收集器命名为“minor gc”,老生代的GC命名为”Full Gc 或者Major GC”.其中用System.gc()强制执行的是Full Gc. 
判断对象是否需要回收的方法有两种: 
1.引用计数 
当某对象的引用数为0时,便可以进行垃圾收集。 
2.对象引用遍历 
果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

触发GC(Garbage Collector)的条件: 
1)GC在优先级最低的线程中运行,一般在应用程序空闲即没有应用线程在运行时被调用。 
2)Java堆内存不足时,GC会被调用。

5. jvm中一次完整的GC流程(从ygc到fgc)是怎样的,重点讲讲对象如何晋升到老年代等

答:对象优先在新生代区中分配,若没有足够空间,Minor GC; 
大对象(需要大量连续内存空间)直接进入老年态;长期存活的对象进入老年态。如果对象在新生代出生并经过第一次MGC后仍然存活,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。

6. 你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms,g1

7. Eden和Survivor的比例分配等

默认比例8:1。 
大部分对象都是朝生夕死。 
复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。 
8. 深入分析了Classloader,双亲委派机制 
ClassLoader:类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。 
双亲委派机制:某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

9. JVM的编译优化

10. 对Java内存模型的理解,以及其在并发中的应用

Java内存模型的主要目标: 定义程序中各个变量的访问规则。 
Java线程之间的通信由Java内存模型(本文简称为JMM)控制。 
所有变量的存储都在主内存,每条线程还都有自己的工作内存,线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作必须在工作内存完成,而不能直接读取主内存中的变量。不同的线程直接无法访问对方工作内存中的变量,线程间变量的传递均需要通过主内存来完成。 

线程间通信: 
1. 首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去。 
2. 然后,线程B到主内存中去读取线程A之前已更新过的共享变量。

11. 指令重排序,内存栅栏等

指令重排序:编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段。在单线程程序中,对存在控制依赖的操作重排序,不会改变执行结果;但在多线程程序中,对存在控制依赖的操作重排序,可能会改变程序的执行结果。

12. OOM错误,stackoverflow错误,permgen space错误

13. JVM常用参数

JVM主要参数:堆设置、回收器选择(串行、并行、并发收集器)

14. tomcat结构,类加载器流程 
 
目录结构: 
• /bin:存放windows或Linux平台上启动和关闭Tomcat的脚本文件 
• /conf:存放Tomcat服务器的各种全局配置文件,其中最重要的是server.xml和web.xml 
• /doc:存放Tomcat文档 
• /server:包含三个子目录:classes、lib和webapps 
• /server/lib:存放Tomcat服务器所需的各种JAR文件 
• /server/webapps:存放Tomcat自带的两个WEB应用admin应用和 manager应用 
• /common/lib:存放Tomcat服务器以及所有web应用都可以访问的jar文件 
• /shared/lib:存放所有web应用都可以访问的jar文件(但是不能被Tomcat服务器访问) 
• /logs:存放Tomcat执行时的日志文件 
• /src:存放Tomcat的源代码 
• /webapps:Tomcat的主要Web发布目录,默认情况下把Web应用文件放于此目录 
• /work:存放JSP编译后产生的class文件

类加载器模式,双亲委派模式: 

15. volatile的语义,它修饰的变量一定线程安全吗

一个变量被定义为volatile之后,具备两重语义:①保证此变量对所有线程的可见性,即当一条线程修改了这个值,新值对于其他所有线程来说是立即得知的,普通变量需要通过主内存传递。②禁止指令重排序优化。 
Volatile修饰的变量不一定是线程安全的,eg非原子操作a++等

16. g1和cms区别,吞吐量优先和响应优先的垃圾收集器选择

CMS收集器:一款以获取最短回收停顿时间为目标的收集器,是基于“标记-清除”算法实现的,分为4个步骤:初始标记、并发标记、重新标记、并发清除。 
G1收集器:面向服务端应用的垃圾收集器,过程:初始标记;并发标记;最终标记;筛选回收。整体上看是“标记-整理”,局部看是“复制”,不会产生内存碎片。 
吞吐量优先的并行收集器:以到达一定的吞吐量为目标,适用于科学技术和后台处理等。 
响应时间优先的并发收集器:保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。

17. 说一说你对环境变量classpath的理解?如果一个类不在classpath下,为什么会抛出ClassNotFoundException异常,如果在不改变这个类路径的前期下,怎样才能正确加载这个类?

classpath是javac编译器的一个环境变量。它的作用与import、package关键字有关。package的所在位置,就是设置CLASSPATH当编译器面对import packag这个语句时,它先会查找CLASSPATH所指定的目录,并检视子目录java/util是否存在,然后找出名称吻合的已编译文件(.class文件)。如果没有找到就会报错! 
动态加载包

18. 说一下强引用、软引用、弱引用、虚引用以及他们之间和gc的关系

强引用:new出的对象之类的引用, 
只要强引用还在,永远不会回收 
软引用:引用但非必须的对象,内存溢出异常之前,回收 
弱引用:非必须的对象,对象能生存到下一次垃圾收集发生之前。 
虚引用:对生存时间无影响,在垃圾回收时得到通知。

计算机的未来在于连接

Java/Python/SOA/Hadoop/Spark

·        博客园

·        首页

·        新随笔

·        联系

·        订阅

·        管理

随笔 -362  文章 - 0  评论 - 1

面试题_31_to_47_JVM底层与GC(Garbage Collection)的面试问题

3164 JVM 中,int 的长度是多数?
Java
中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 64 Java 虚拟机中,int 类型的长度是相同的。

32Serial Parallel GC之间的不同之处?(答案)
Serial
Parallel GC执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认的复制收集器,执行 GC 的时候只有一个线程,而 parallel 收集器使用多个 GC 线程来执行。

3332 位和 64 位的 JVMint 类型变量的长度是多数?(答案)
32
位和 64 位的 JVM 中,int 类型变量的长度是相同的,都是 32 位或者 4 个字节。

34Java WeakReference SoftReference的区别?(答案)
虽然 WeakReference SoftReference 都有利于提高 GC 内存的效率,但是 WeakReference ,一旦失去最后一个强引用,就会被 GC 回收,而软引用虽然不能阻止被回收,但是可以延迟到 JVM 内存不足的时候。

35WeakHashMap是怎么工作的?(答案)
WeakHashMap
的工作与正常的 HashMap 类似,但是使用弱引用作为 key,意思就是当 key 对象没有任何引用时,key/value 将会被回收。

36JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要使用?(答案)
当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从 32 位增加到了 64 位,因此堆内存会突然增加,差不多要翻倍。这也会对 CPU 缓存(容量比内存小很多)的数据产生不利的影响。因为,迁移到 64 位的 JVM 主要动机在于可以指定最大堆大小,通过压缩 OOP 可以节省一定的内存。通过 -XX:+UseCompressedOops 选项,JVM 会使用 32 位的 OOP,而不是 64 位的 OOP

37)怎样通过 Java 程序来判断 JVM 32 还是 64 位?(答案)
你可以检查某些系统属性如 sun.arch.data.model os.arch 来获取该信息。

3832 JVM 64 JVM 的最大堆内存分别是多数?(答案)
理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多。不同操作系统之间不同,如 Windows 系统大约 1.5 GBSolaris 大约 3GB64 JVM允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。

39JREJDKJVM JIT 之间有什么不同?(答案)
JRE
代表 Java 运行时(Java run-time),是运行 Java 引用所必须的。JDK 代表 Java 开发工具(Java development kit),是 Java 程序的开发工具,如 Java 编译器,它也包含 JREJVM 代表 Java 虚拟机(Java virtual machine),它的责任是运行 Java 应用。JIT 代表即时编译(Just In Time compilation),当代码执行的次数超过一定的阈值时,会将 Java 字节码转换为本地代码,如,主要的热点代码会被准换为本地代码,这样有利大幅度提高 Java应用的性能。

3 年工作经验的 Java 面试题

40)解释 Java 堆空间及 GC(答案)
当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC JVM 内部的一个进程,回收无效对象的内存用于将来的分配。

 

JVM 底层面试题及答案

41)你能保证 GC 执行吗?(答案)
不能,虽然你可以调用 System.gc() 或者 Runtime.gc(),但是没有办法保证 GC 的执行。

42)怎么获取 Java 程序使用的内存?堆使用的百分比?
可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory() 方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。

43Java 中堆和栈有什么区别?(答案)
JVM
中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。

 

关于内存的的面试问题和答案

Java 基本概念面试题

44“a==b””a.equals(b)”有什么区别?(答案)
如果 a b 都是对象,则 a==b 是比较两个对象的引用,只有当 a b 指向的是堆中的同一个对象才会返回 true,而 a.equals(b) 是进行逻辑比较,所以通常需要重写该方法来提供逻辑一致性的比较。例如,String 类重写 equals() 方法,所以可以用于两个不同对象,但是包含的字母相同的比较。

45a.hashCode()有什么用?与 a.equals(b) 有什么关系?(答案)
hashCode()
方法是相应对象整型的 hash 值。它常用于基于 hash 的集合类,如 HashtableHashMapLinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java规范,两个使用 equal() 方法来判断相等的对象,必须具有相同的 hash code

46finalfinalize finally 的不同之处?(答案)
final
是一个修饰符,可以修饰变量、方法和类。如果 final 修饰变量,意味着该变量的值在初始化后不能被改变。finalize 方法是在对象被回收之前调用的方法,给对象自己最后一个复活的机会,但是什么时候调用 finalize 没有保证。finally 是一个关键字,与 try catch 一起用于异常的处理。finally 块一定会被执行,无论在 try 块中是否有发生异常。

47Java 中的编译期常量是什么?使用它又什么风险?
公共静态不可变(public static final )变量也就是我们所说的编译期常量,这里的 public可选的。实际上这些变量在编译时会被替换掉,因为编译器知道这些变量的值,并且知道这些变量在运行时不能改变。这种方式存在的一个问题是你使用了一个内部的或第三方库中的公有编译时常量,但是这个值后面被其他人改变了,但是你的客户端仍然在使用老的值,甚至你已经部署了一个新的jar。为了避免这种情况,当你在更新依赖 JAR 文件时,确保重新编译你的程序。

 

GC(垃圾处理机制)面试题

转载 2014年03月30日 16:49:46

·        标签:

·        javagc

·        4440

GC(垃圾处理机制)



1: 详细解释Java中垃圾收集的主要流程。 

垃圾收集主要有两种形式:手工、自动

自动会不定期进行回收,以释放无用的空间

手工调用的是System类中的gc()方法,此方法实际上调用的是Runtime类中的gc()方法,当一个对象被回收之前将调用类中的finlalize()方法,此方法为 Object类所提供,表示对象回收前的收尾工作。即使出现了异常,也不影响程序的执行,而且此方法抛出的是Throwable,表示可能是异常也可能是错误。

 

2、GC是什么? 为什么要有GC? 

  GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能     可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

 

3、垃圾回收的优点和原理。并考虑2种回收机制。

http://blog.csdn.net/nysyxxg/article/details/8789358

 

 

Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制, Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

 

4、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?

 对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

 

 

5、垃圾回收机制,如何优化程序? 

 

    Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。 

 

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。 

 

回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

垃圾回收机制 垃圾收集是将分配给对象但不再使用的内存回收或释放的过程。如果一个对象没有指向它的引用或者其赋值为null,则次对象适合进行垃圾回收.

垃圾回收机以低优先级运行 

检查不被使用和指向的对象 

把它删除

有关GC的面试题

原创 2014年03月27日 14:01:03

·        2353

1

Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间。

需要注意的是:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身,很多人来我公司面试时,我都会问这个问题的,70%以上的人回答的含义是回收对象,实际上这是不正确的。

System.gc()

Runtime.getRuntime().gc() 

上面的方法调用时用于显式通知JVM可以进行一次垃圾回收,但真正垃圾回收机制具体在什么时间点开始发生动作这同样是不可预料的,这和抢占式的线程在发生作用时的原理一样。

2

现行的GC采用分代的方式来采用不同的回收设计。

分代的基本思路是根据对象的生存时间长短,把堆内存分成三个代

Young  复制算法

Old  标记压缩算法(综合了复制算法与标记算法的特点) 

Permanent

3、内存管理小技巧

1)尽量使用直接量。

2)使用StringBuilderStringBuffer进行字符串连接。

3)尽早释放无用对象的引用。

4)尽量少用静态变量。最坏的情况是当某一个对象被static变量所引用,那么GC通常是不会回收该对象所占内存。

5)避免在经常调用的方法、循环中创建Java对象。

6)缓存经常使用的对象。比如使用HashMap

7)尽量不要使用finalize方法。

8)考虑使用SoftReference

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值