JVM(一)--JVM的内存区域划分以及相关知识点

JVM(一)–JVM的内存区域划分以及相关知识点

一、JVM的内存区域是怎么划分的?

JVM结构图

在这里插入图片描述
JVM = 类加载器 + 执行引擎 + 运行时数据区

  • 类加载器(Class Loader):把硬盘上的class文件加载到JVM中的运行时数据区域,它不负责这个类文件是否能够执行
  • 执行引擎(Execution Engine):负责这个类文件是否能够执行。执行字节码,或者执行执行本地方法

运行时数据区:

JVM的内存划分中,有部分区域是线程私有的,有部分是属于整个JVM进程;有些区域会抛出OOM异常,有些则不会,了解JVM的内存区域划分以及特征,是定位线上内存问题的基础。那么JVM内存区域是怎么划分的呢?

在这里插入图片描述
1,程序计数器:

首先是程序计数器(Program Counter Register),在JVM规范中,每个线程都有自己的程序计数器。这是一块比较小的内存空间,存储当前线程正在执行的Java方法的JVM指令地址,即字节码的行号(它可以看作是当前线程所执行的字节码的行号指示器)。在JMM中,字节码解释器工作时就是通过改变这个计数器的值来选取吓一跳需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等急促功能都需要一来这个计数器来完成

异常情况:

如果正在执行Native方法,则这个计数器为空。该内存区域是唯一一个在Java虚拟机规范中没有规定任何OOM情况的内存区域。

为什么需要程序计数器?(为什么程序计数器是私有的?)

由于JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储

2. Java虚拟机栈:

Java虚拟机栈(Java Virtal Machine Stack),同样也是属于线程私有区域每个线程在创建的时候都会创建一个虚拟机栈,生命周期与线程一致,线程退出时,线程的虚拟机栈也回收。虚拟机栈内部保持一个个的栈帧(栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构(在之后的文章中会具体讲解)。这个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。),每次方法调用都会进行压栈,JVM对栈帧的操作只有出栈和压栈两种,方法调用结束时会进行出栈操作。

该区域存储着局部变量表,编译时期可知的各种基本类型数据、对象引用、方法出口等信息。

在这里插入图片描述

  • 局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型
  • 局部变量表所需要的内存空间在编译期间完成分配当进入一个方法时,这个方法需要在栈中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小因为在编译期间已经完成分配了。

异常情况:

  • 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
  • 如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常

3,本地方法栈:

本地方法栈(Native Method Stack)与虚拟机栈类似本地方法栈是在调用本地方法时使用的栈,每个线程都有一个本地方法栈

本地方法栈保存的是native方法信息,当一个jvm创建的线程调用native方法后,jvm不再为其在虚拟机栈中创建栈帧,jvm只是简单地动态连接并直接调用native方法。

本地方法栈与虚拟机栈的区别:

  • 虚拟机栈为虚拟机执行java方法服务(即字节码服务)
  • 本地方法栈则为虚拟机使用到的Native方法服务

异常情况:

与虚拟机栈类似,也会抛出:

将抛出StackOverflowError异常和OutOfMemoryError异常

4,java堆:

  • 堆(Heap),几乎所有创建的Java对象实例,都是被直接分配到堆上的
  • 堆被所有的线程所共享,在堆上的区域,会被垃圾回收器做进一步划分,例如新生代、老年代的划分。
  • 也就是java堆是垃圾收集器管理的主要区域,因此很多时候也被称为”GC堆”
  • Java虚拟机在启动的时候,可以使用“Xmx”之类的参数指定堆区域的大小。

异常情况:

如果堆中没有内存完成实例分配,并且堆已经无法再扩展时,将会抛出OutOfMemoryError异常。

5,方法区:

为什么叫方法区?简单的来说:方法区主要存class,class里面最重要的就是方法,所以称之为方法区。(里面的东西时很难发生变化的)

  • 方法区(Method Area)。方法区与堆一样,也是所有的线程所共享

  • 存储被虚拟机加载的元(Meta)数据,包括类信息、常量、静态变量、即时编译器编译后的代码等数据(也就是class元数据)

  • 里需要注意的是运行时常量池也在方法区中

  • 由于早期HotSpot JVM的实现,将GC分代收集拓展到了方法区,因此很多人会将方法区称为永久代。Oracle JDK8中已永久代移除永久代同时增加了元数据区(Metaspace)

  • 所以,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代名字一样”永久“存在。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载

在这里插入图片描述

异常情况:

根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

6,运行时常量池:

  • 运行时常量池(Run-Time Constant Pool),这是方法区的一部分,受到方法区内存的限制,当常量池无法再申请到内存时,会抛出OutOfMemoryError异常。
  • Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池常量池存放编译器生成的各种字面量和符号引用。这部分内容将在类加载后进入方法区的运行时常量池中存放
    • 字面量:文本字符串生命为final的常量值
    • 符号引用:类和接口的完全限定名,字段的名称与描述符,方法的名称与描述符(存放了与编译相关的一些常量,因为Java不像C++那样有连接的过程,因此字段方法这些符号引用在运行期就需要进行转换,以便得到真正的内存入口地址。
  • 运行时常量池相对于Class文件常量池的另一个重要特征是具备动态性,java语言并不要求敞亮一定只有编译器才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的敞亮放入池中,这种特性被开发人员用得比较多的便是String类的intern()方法

class文件中的常量池,也称为静态常量池,JVM虚拟机完成类装载操作后,会把静态常量池加载到内存中,存放在运行时常量池

异常情况:

运行时常量池(Run-Time Constant Pool),这是方法区的一部分,受到方法区内存的限制,当常量池无法再申请到内存时,会抛出OutOfMemoryError异常

7. 直接内存:

  • 直接内存(Direct Memory),直接内存并不属于Java规范规定的属于Java虚拟机运行时数据区的一部分
  • 在JDK1.4中新加入了NIO类,引入了一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作

异常情况:

直接内存并不会受到java堆大小的限制,但是既然是内存,还是会受本机总内存大小以及处理器寻址空间的限制。所以,当各个内存区域总和大于物理内存限制,从而导致动态扩展时出现OutOfMemoryError异常。

下面这张图,反映了运行中的Java进程内存占用情况:

在这里插入图片描述

二、OOM可能发生在哪些区域上?

根据javadoc的描述,OOM是指JVM的内存不够用了,同时垃圾收集器也无法提供更多的内存。从描述中可以看出,在JVM抛出OutOfMemoryError之前,垃圾收集器一般会出马先尝试回收内存。

从上面分析的Java数据区来看,除了**程序计数器不会发生OOM**外,哪些区域会发生OOM的情况呢?

第一,堆内存。堆内存不足是最常见的发送OOM的原因之一,如果在堆中没有内存完成对象实例的分配,并且堆无法再扩展时,将抛出OutOfMemoryError异常。当前主流的JVM可以通过**-Xmx和-Xms来控制堆内存的大小**,发生堆上OOM的可能是存在内存泄露,也可能是堆大小分配不合理

第二,Java虚拟机栈和本地方法栈,这两个区域的区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务,在内存分配异常上是相同的。在JVM规范中,对Java虚拟机栈规定了两种异常:

  • 如果线程请求的栈大于所分配的栈大小,则抛出StackOverFlowError错误,比如进行了一个不会停止的递归调用;
  • 如果虚拟机栈是可以动态拓展的,拓展时无法申请到足够的内存,则抛出OutOfMemoryError错误。

第三,直接内存。直接内存虽然不是虚拟机运行时数据区的一部分,但既然是内存,就会受到物理内存的限制。在JDK1.4中引入的NIO使用Native函数库在堆外内存上直接分配内存,但直接内存不足时,也会导致OOM。

第四,方法区。随着Metaspace元数据区的引入,方法区的OOM错误信息也变成java.lang.OutOfMemoryError:Metaspace。

对于旧版本的Oracle JDK,由于永久代的大小有限,而JVM对永久代的垃圾回收并不积极,如果往永久代不断写入数据,例如String.Intern()的调用,在永久代占用太多空间导致内存不足,也会出现OOM的问题,对应的错误信为java.lang.OutOfMemoryError:PermGen space

在这里插入图片描述

三、谈谈你对OOM的认识:

主要有:

  • java.lang.StackOverflowError
  • java.lang.OutOfMemoryError:java heap space
  • java.lang.OutOfMemoryError:GC overhead limit exceeded
  • java.lang.OutOfMemoryError:Direct buffer memory
  • java.lang.OutOfMemoryError:unable to create new native thread
  • java.lnag.OutOfMemoryError:Metaspace

类图架构为:
在这里插入图片描述

1,java.lang.StackOverflowError:(是一种错误不是异常)

其组织架构为:

java.lang.Object
	java.lang.Throwable
		java.lang.Error//这里是Error,所以这个是一个错误不是异常
			java.lang.VirtualMachineError
				java.lang.StackOverflowError

从以上的结构中可以看出,这个java.lang.StackOverflowError不是一个异常而是一个错误

这个StackOverflowError:也就是递归调用方法以后,方法特别多把栈空间给撑爆了

2,java.lang.OutOfMemoryError:java heap space(是一种错误不是异常)

java.lang.OutOfMemoryError:java heap space:对象太多,堆给撑爆了。

这里牵涉到一个问题
堆大小30M,数组存在于堆中,25M的数组,为什么会报OOM?

因为堆中分老年代+年轻代(新生代10M(Eden 8M,Survior 1M),老年代 20M),所以这个25M放在新生代还是老年代都放不下的,所以会报OOM

3,java.lang.OutOfMemoryError:GC overhead limit exceeded:

GC回收时间过长时会抛出OutOfMemoryError过长的定义是:超过98%的时间用来做GC,并且回收了不到2%的堆内存,连续多次GC,都回收了不到2%的极端情况下才会抛出。假设不抛出GC overhead limit 错误会发生什么情况呢?那就是GC清理的这么点内存很快就会被再次填满,迫使GC再次执行,这样会形成恶性循环,cpu使用率一直是100%,而GC却没有任何成果。

在这里插入图片描述

好的应该是:GC前空间(较小)–>GC后空间(较大)

4,java.lang.OutOfMemoryError:Direct buffer memory:

导致原因写NIO程序经常会使用ByteBuffer来读取或者写入数据,这是一种基于通道(channe)与缓冲区(buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作,这样能在一些场景中显著提高性能,因为避免了在java堆和Native堆中来回复制数据

ByteBuffer.allocate(capacity):第一种方式是分配了JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢
ByteBuffer.allocateDirect(capacity):这是一种方式分配了os本地内存,不属于GC管辖范围,由于不需要内存拷贝,所以速度较快

但如果不断的分配本地内存,堆内存很少使用,则JVM就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,但本地内存可能已经使用光了,再次尝试分配本地内存就会出现OOM,那程序就直接崩溃了。(==>最大的java本地内存,一般为本地内存的1/4

在这里插入图片描述
5,java.lang.OutOfMemoryError:unable to create new native thread:(这个问的很多)

(高并发请求服务器时经常出现如下异常 java.lang.OutOfMemoryError:unable to create new native thread,准确的说,该native thread异常与对应的平台有关)

导致原因:①你的应用创建了太多的线程了,一个应用线程创建多个线程,超过了系统承载极限了 ②你的服务器并不允许你的应用程序创建这么多个线程,linux系统默认允许单个线程可以创建的线程数是1024个,你的应用创建超过这数量,就会报 java.lang.OutOfMemoryError:unable to create new native thread。

**解决方法:**①想办法降低你的应用程序创建线程的数量,分析应用是否真的需要创建这么多的线程,若不是,改代码将线程数降到最低 ②对于你的应用,确实需要创建很多的线程,远超过linux系统的默认值1024个线程的限制,可以通过修改linux服务器配置,扩大linux默认极限。

6,java.lnag.OutOfMemoryError:Metaspace:

使用java-XX:+PrintFlagsInitial命令查看本机的初始化参数,-XX:Metaspacesize为2181036B 大约为20.8M

java8及之后的版本使用Metaspace来替代永久代。Metaspace是方法区HotSpot的实现,它与持久化最大的不同就是Metaspace并不在虚拟机内存而是使用本地内存

四、你平时工作中用过的jvm常用基本配置参数有哪些?

常用参数:

  • -Xms:初始化大小内存,等价于-XX.InitialHeapSize
  • -Xmx:最大分配内存,等价于-XX.MxHeapSize
  • -Xss:设置单个线程栈的大小,等价于-XX.ThreadStackSize
  • -Xmn:设置年轻代的大小(一般为默认)
  • -XX:MetaspaceSize:设置元空间大小:元空间不再虚拟机中,而是使用本地内存(默认为20多兆,为了防止挤爆,有时需要调大一些,比如1024M)
  • -XX:+PrintGcDetails:输出详细GC收集日志信息
  • -XX:SurviorRation:设置新生代中eden和s0/s1空间的比例(默认,Eden:s0:s1=8:1:1(s0与s1相同))
  • -XX:NewRatio:配置年轻代与老年代在堆结构中的占比(NewRation可就是设置老年代的占比,剩下的给新生代)
  • -XX:MaxTenuringThreshold:设置垃圾最大年龄(比如15,则经过15次GC就晋升都老年区)(默认为1~15,一般为15)

五、你说说你做过的jvm调优和参数设置,请问如何盘点查看jvm系统默认值?

  • Xss:初始化栈空间
  • Xms:初始化堆空间
  • Xmx:堆的最大值
    (一般Xms和Xmx这两个最好调成一致)

JVM的参数类型:

  • 1,标配参数:
    • -version和-help:在jdk各个版本之间稳定,很少有大的变化
    • java -showversion
  • 2,X参数(了解):
    • -Xint:解释执行
    • -Xcomp:第一次使用就编译成本地代码
    • -Xmixed:混合模式(也就是先编译再执行)
  • 3,XX参数:
    • ①Boolean类型:

-XX:+/-某个属性值(+表示开启,-表示关闭)

  • ②KV设置类型(键值对):

公式:-XX:属性key=属性值value
比如:-XX:MetaspaceSize=128M
-XX:MaxTenuringThreshold=15

  • ③jinfo举例,如何查看当前运行程序的配置:

公式:jinfo-flag配置项 进程编号

如:jinfo-flag InitialHeapSize 8372(初始化堆大小)
jinfo-flags 5988(找出5988进程所有的能查出的信息)

  • ④题外话(坑提):

两个经典参数:-Xms和-Xmx

-Xms:等价于-XX:InitialHeapSize(初始化堆大小)
-Xmx:等价于-XX:MaxHeapSize(最大堆大小)

如何查看一个正在运行中的java程序,它的某个jvm参数是否开启?具体值是多少?

  • jps:查看java的后台进程
  • jinfo:查看正在运行中的java程序的各组信息

第一种:查看参数盘点家底:
jps:
jinfo -flag 具体参数 java进程编号
jinfo -flags 多个参数 java进程编号

第二种:查看参数盘点家底:

①java -XX:PrintFlagsInitial:(没有运行程序时所有初始化默认的参数)==>也就是出厂默认的参数
②-XX:PrintFlagsFinal:主要查看修改更新

公式:java -XX:+PrintFlagsFinal -version

③-XX:=PrintCommandLineFlags:打印命令行参数

在这里插入图片描述

感谢并参考:

java知音
https://blog.csdn.net/xiaojie_570/article/details/80094819

热门文章

暂无图片
编程学习 ·

sqlserver:临时表的删除

遇到一个坑: 某天,定时作业失败了多次,但代码没变动,这就奇了怪了。。 结果:经检查,每次执行的时候,临时表若存在,就会失败。 分析:当初不写删除临时表,是查询了临时表的定义,会话内自动结束,不知道是哪出现了问题。 解决: if OBJECT_ID(tempdb..#tempList) is no…
暂无图片
编程学习 ·

MIT 计算机操作环境导论Missing Semester Lesson 10 Q&A

最后一节课,我们回答学生提出的问题:学习操作系统相关内容的推荐,比如进程,虚拟内存,中断,内存管理等你会优先学习的工具有那些?使用 Python VS Bash脚本 VS 其他语言?source script.sh 和 ./script.sh 有什么区别?各种软件包和工具存储在哪里?引用过程是怎样的? /bi…
暂无图片
编程学习 ·

[UML] 类图之间的关系 | 3.泛化关系

[UML] 类图之间的关系 | 3.泛化关系 3.泛化关系泛化(Generalization)关系也就是**继承关系**,用于描述父类与子类之间的关系,父类又称为基类或超类,子类又称为派生类 在UML中,泛化关系用带空心三角形的直线来表示 在代码实现时,使用面向对象的继承机制来实现泛化关系,在J…
暂无图片
编程学习 ·

90后绝对不是用来管的!

作者:混沌大学来源:混沌大学(ID:hundun-university) 在知乎上,“如何管理90后员工”是一个长盛不衰的话题。一个备受关注的问题是这样的:最近公司录用了一批90后的新员工,基本上全都离职了,最短的半天,最长的也就工作了一周,迫切地想知道90后员工的求职观,什么样的…
暂无图片
中恒嘉业 ·

关于主从复制的超详细解析(全)

目录前言1. 主从复制1.1 方式2. Mysql的主从复制2.1 一主一从2.1.1 window和linux通讯2.1.2 linux和linux的通讯2.2 双主双从3. Redis的主从复制3.1 哨兵模式3.2 java代码结合前言 主要介绍mysql的主从复制以及redis的主从复制 能由浅入深的明白原理以及如何操作 再者&#xf…
暂无图片
郑州普通话 ·

apm性能监控系统,kotlindata类

进阶之路 为何会想起写这么一篇文章呢,一方面很多程序员对于技术精进仍然十分困惑,不知道该如何学习进阶,以至于提前陷入中年危机的困惑之中,作为一名Android开发近十年的老码农或许可以分享一些自己的心得体会,刚好这几天工作需要,组内想规划 Android 技术路线,简单来说…
暂无图片
郑州普通话 ·

将Jetson XavierNX的Ubuntu系统迁移至到nvme硬盘上

第一步:sudo mke2fs -t ext4 /dev/nvme0n1p1 #格式化分区 第二步:将eMMC / SD卡的rootfs复制到SSD git clone https://github.com/jetsonhacks/rootOnNVMe cd rootOnNVMe #进入目录 ./copy-rootfs-ssd.sh #执行复制脚本第三步:安装启动脚本…
暂无图片
代理记账 ·

在web应用中发送和接收Jakarta消息

Running the websimplemessage Example To Package and Deploy websimplemessage Using Maven _1、Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server). _2、In a terminal window, go to: tut-install/examples/jms/websimp…
暂无图片
cgfy ·

C++学习日记2——函数、封装、对象特性

一、函数 1.1 函数默认参数 1.1.1 简介 在C中&#xff0c;函数的形参列表中的形参是可以有默认值的 1.1.2 语法 返回值类型 函数名 (参数 默认值) {} 1.1.3 代码 #include <iostream> using namespace std;// 函数的默认参数 int func(int a, int b 20, int c 30…
暂无图片
coreui ·

视频水印怎么去除?超简单 千万不要错过

小编在知乎看到很多大佬分享的视频去水印的方法&#xff0c;但是感觉都有点太复杂了&#xff0c;今天就来分享一下小编自己私藏的几个针对于视频去水印的软件和网站~建议大家收藏哦~ 1、爱给网-视频去水印小工具&#xff08;免费 在线&#xff09; 推荐点 1、在线操作&#…
暂无图片
coreui ·

Mac 安装 tomcat10

Mac 安装 tomcat10 1、下载tomcat tomcat官网&#xff1a;https://tomcat.apache.org/ 点击我下载的tomcat10&#xff1a; 2、下载解压,给bin下的*.sh文件添加可执行权限 3、修改webapps下的ROOT中的index文件查看效果
暂无图片
未来博客 ·

视频水印怎么去除?超简单 千万不要错过

小编在知乎看到很多大佬分享的视频去水印的方法&#xff0c;但是感觉都有点太复杂了&#xff0c;今天就来分享一下小编自己私藏的几个针对于视频去水印的软件和网站~建议大家收藏哦~ 1、爱给网-视频去水印小工具&#xff08;免费 在线&#xff09; 推荐点 1、在线操作&#…
暂无图片
未来博客 ·

Mac 安装 tomcat10

Mac 安装 tomcat10 1、下载tomcat tomcat官网&#xff1a;https://tomcat.apache.org/ 点击我下载的tomcat10&#xff1a; 2、下载解压,给bin下的*.sh文件添加可执行权限 3、修改webapps下的ROOT中的index文件查看效果
暂无图片
建站日记 ·

惠州实验室建设选址、勘察事项

惠州实验室建设选址、勘察事项&#xff0c;SICOLAB技术员带您从实验室建设启动前思考问题考虑如下&#xff1a;一、不同实验室建设选址要求 1.化学实验室 &#xff08;1&#xff09;清洁安静环境 &#xff08;2&#xff09;远离住宅、生活区 &#xff08;3&#xff09;锅炉房与…
暂无图片
建站日记 ·

NLP聊天机器人原理(seq2seq模型)

一、seq2seq模型 1.概念 seq2seq是一个Encoder-Decoder结构的网络&#xff0c;它的输入是一个序列&#xff0c;输出也是一个序列。Encoder中将一个可变长度的信号序列变为固定长度的向量表达&#xff0c;Decoder将这个固定长度的向量变成可变长度的目标的信号序列。这个结构最…
暂无图片
mfbz ·

惠州实验室建设选址、勘察事项

惠州实验室建设选址、勘察事项&#xff0c;SICOLAB技术员带您从实验室建设启动前思考问题考虑如下&#xff1a;一、不同实验室建设选址要求 1.化学实验室 &#xff08;1&#xff09;清洁安静环境 &#xff08;2&#xff09;远离住宅、生活区 &#xff08;3&#xff09;锅炉房与…
暂无图片
mfbz ·

全渠道会员通-天猫会员通3: 会员运营内容准备

在天猫会员通技术对接开发过程中&#xff0c;为了通知存量会员的通知工作&#xff0c;发挥会员通的优势&#xff0c;品牌需要做好以下事宜&#xff1a; 会员体系暂停公告&#xff1a;因会员通技术升级期间&#xff0c;会员服务将被暂停&#xff0c;店铺tab中会员入口将被下线&…
暂无图片
珊珊日记 ·

C# 执行Javascript脚本

c#教程https://www.xin3721.com/eschool/CSharpxin3721/ 前一阵子使用C#编写SCXML状态机&#xff0c;需要解析EMCScript表达式&#xff0c;使用了Jint库&#xff08;https://github.com/sebastienros/jint/)&#xff0c;当时感觉与C#之间的数据转换不是很方便。这两天有时间又关…
暂无图片
珊珊日记 ·

第九届“图灵杯”NEUQ-ACM程序设计竞赛个人赛

A.大学期末现状 题目描述 作为一名大学生的你&#xff0c;现在又到了期末查成绩的时候&#xff0c;当你的成绩大于等于60时请输出“jige,haoye!”,否则输出"laoshi,caicai,laolao"。 输入描述: 一行&#xff0c;一个整数x代表你的成绩&#xff08;0<x<100&a…