JVM调参实践总结

JVM调优–理论篇从理论层面介绍了如何对JVM调优。这里再写一篇WIKI,尝试记录下JVM参数使用的最佳实践,注意,这里重点介绍HotSpot VM的调参,其他JVM的调参可以类比,但不可照搬。

Java版本选择

基于Java开发应用时,第一个要考虑的问题,就是Java版本的选择。一般情况下,一个团队或一个组织使用相同的Java版本。由于现在Java版本的发布周期是半年一个版本,所以在实际应用中应选择发行版本,目前支持的发行版本有Java 11、Java 17、Java 21。当然,很大一部分厂商使用Java 8。尽管Java官方目前已不在直接支持Java 8的发行版本,但是Java 8因其广泛且长久的使用,已经非常稳定,且部分有能力的厂商还在维护Java 8,所以Java 8也是一个不错的选择。更多Java版本信息可以参考官网。注意,Java提供的版本均是收费版本,如果需要获取免费版本,可以获取OpenJDK。OpenJDK是Java语言的一个开源实现,OpenJDK采用GPL协议,主要组件包括Hotspot JVM、Java核心类库和javac编译器。OpenJDK具有开源免费、跨平台、高性能和多版本支持等特点,适用于Java应用程序开发、桌面应用程序等多种场景。可以从adoptium网站获取已编译的OpenJDK版本。

JVM类型选择

Java提供了Java Language and Virtual Machine Specifications,约定了JVM的实现细节,这样不同的厂商可以实现自己的JVM。目前,主流的JVM有:HotSpot VM、IBM JVM、Open JDK、GraalVM等。在选用JVM类型时,根据稳定性、高性能、安全性、可维护性、费用等方面组合考虑。如在Java 8中,通常使用Oracle的HotSpot JVM。如果期望使用免费版本,可以选择Open JDK。

JVM部署平台相关选择

JVM部署时,是选择32位JVM,还是64位JVM。HotSpot VM默认的执行位数取决于所安装的JDK版本和操作系统。在32位操作系统上,只能运行32位的JDK,因此HotSpot虚拟机也只能在32位模式下执行。而在64位操作系统上,可以选择安装32位或64位的JDK。如果安装了64位的JDK,那么HotSpot虚拟机将默认在64位模式下执行。推荐在64位操作上安装64位的JDK版本。注意,不同操作系统上,对应的版本不同,所以在选择JVM位数的同时,也要注意选择和待部署操作系统向匹配的版本。此外,针对不同的CPU架构,JVM的版本也不尽相同。在选择JVM执行位数时,还应考虑CPU架构。

JVM部署模式选择

JVM部署模式指的是将应用部署到单个JVM实例上,还是部署多个JVM实例上。目前应用的主流架构是微服务架构。对一个应用来说,常常需要拆分成多个独立的微服务。对于每个微服务来说,为了保证其高可用,通常需要多个实例。所以,对于一个大型的应用来说,是将其拆分成微服务单独部署。而对一个微服务,会对应多个服务实例,且每个每个服务部署在隔离的环境中,如Kubernetes的Pod中。JVM部署模式是架构层面需要考虑的事情,针对一个Java进程来说,无需考虑。

JVM运行模式

为Java应用选择JVM运行模式,就是指定以何种方式运行JVM,可选项有:client模式、server模式和混合模式。注意,混合模式是在Java 7及之后的版本才引入。推荐使用混合模式,这也是Java 8及之后的版本默认的运行模式。该模式可以很好地融合client模式和Server模式的主要特征。如无特殊说明,使用混合模式即可,除非有明确诉求需要使用client模式或server模式。选用server模式启动JVM的示例命令如下:

java -server -jar hello-world.jar

上述示例命令中,使用server模式启动了一个hello-world的Java应用。

垃圾收集器选择

JVM的一个重要职责是实现内存的自动化管理。而实现内存的自动化管理的关键就是垃圾收集器。垃圾收集主要关注的性能属性有:吞吐量、延迟、内存占用。其中:
(1) 吞吐量:是评价垃圾收集器能力的重要指标之一,指不考虑垃圾收集引起的停顿时间或内存消耗,垃圾收集器能支撑应用达到的最高性能指标。
(2) 延迟:也是评价垃圾收集器能力的重要指标,度量标准是缩短由于垃圾收集引起的停顿时间或完全消除因垃圾收集所引起的停顿,避免应用运行时发生抖动。
(3) 内存占用:垃圾收集器流畅运行所需要的内存数量。
这其中任何一个属性性能的提高几乎都是以另一个或两个属性性能的损失作代价的。换句话说,某一个属性上的性能提高总是牺牲另一个或两个属性。然而,对大多数应用来说,极少出现这三个属性的重要程度都同等的情况。很多时候,某一个或两个属性的性能要比另一个重要。哪个属性最重要,并将其映射到应用的系统需求,对应用而言非常重要。
同一个JVM中,可能包含多种垃圾收集器实现。在选择垃圾收集器时,要根据应用的需求,进行一个初步的选择。在HotSpot VM中,如果应用对停顿时间要求较为严格(即不希望因为垃圾收集而导致过多的暂停),那么可能需要选择那些停顿时间较短的垃圾收集器,如CMS收集器或G1收集器。相反,如果应用对停顿时间要求不那么严格,可以考虑使用串行收集器或并行收集器,它们在垃圾收集时可能会暂停所有工作线程。如果对较小的堆或较低配置的硬件,可能更适合使用简单的串行收集器或者并行收集器。对于大内存堆和多核CPU的环境,可以考虑使用G1等垃圾收集器,它们更适合大规模的堆和高配置的硬件。垃圾收集器的选择,要根据业务的特征,进行充分的测试。初步选择后,如果经过测试后,并不能达到预期,则要考虑换用垃圾收集器,并重新进行测试。
在进行垃圾收集验证时,一般从默认垃圾收集器开始。Java 8默认的垃圾收集器是Parallel Scavenge和Parallel Old。这是Oracle JDK 8中的默认设置,适用于大多数应用程序场景。但在某些特定场景下,可能需要选择其他更适合的垃圾收集器,如CMS收集器或G1收集器。指定CMS收集器或G1收集器的示例命令如下:

# 指定使用CMS垃圾收集器
java -XX:+UseConcMarkSweepGC hello-world.jar
# 指定使用G1垃圾收集器
java -XX:+UseG1GC -jar hello-world.jar

CMS收集器在Java 9之后已被标记为废弃(deprecated),并在后续的Java版本中被移除。因此,如果正在使用Java 9或更高版本,并且希望使用类似的低延迟垃圾收集器,应该考虑使用G1(Garbage-First)收集器,它是Java 9之后的默认收集器,并且也旨在提供可预测的停顿时间。G1收集器在Java 9及更高版本中通常是一个更好的选择,因为它提供了更好的性能和更灵活的垃圾收集配置选项。不过,具体的选择应该基于你的应用程序的需求和性能目标。

垃圾收集器的进一步优化

不同的垃圾收集器还提供了一系列参数,帮助进一步对垃圾收集器进行调优。这里以G1收集器为例,介绍下常用的调优命令。

java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar hello-world.jar

-XX:MaxGCPauseMillis参数用来设置垃圾收集的最大暂停时间,这样垃圾收集对延迟或响应的影响就变得可控。

垃圾收集报告

监控JVM的垃圾收集非常重要,因为垃圾收集对应用的吞吐量和延迟都有着深刻的影响。HotSpot VM报告垃圾收集数据几乎没有什么额外开销,推荐在测试环境启用该配置,但不建议在生产环境中使用。生成垃圾收集统计数据的命令行如下:

# Java 8及更早版本启用记录详细的GC日志
java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log -jar hello-world.jar
# Java 9及更高版本启用记录详细的GC日志
java -Xlog:gc*:file=gc.log -jar hello-world.jar

上述命令中,-XX:PrintGCDetails参数用来打印比-verbose:gc参数更多有价值的垃圾收集信息。注意,在生产环境中启用-verbose:gc或-XX:PrintGCDetails参数,或其他详细的GC日志可能会产生大量的输出,这可能会对应用程序的性能产生轻微的影响。因此,通常建议仅在开发和测试阶段使用这些参数,以便在必要时进行调优和分析。此外,-XX:PrintGCDetails参数打印的日志包含时间戳前缀,这个时间是自JVM启动以来的秒数。为了生成标准时间戳,形如YYYY-MM-DD-T-HH-MM-SS.mmm-TZ,可以补充-XX:PrintGCDateStamps参数。为了更好的分析垃圾收集器的统计数据,还可以使用-Xloggc:<filename>将垃圾收集的统计数据直接输出到文件(filename是保存的文件名)。离线分析可以处理时间范围更广的垃圾收集数据,查找问题时也不会直接影响线上应用。
在Java 9及更高的版本,使用新的日志系统,称为统一日志记录(Unified Logging),它使用-Xlog参数来配置各种日志,包括垃圾收集(GC)日志。-Xlog:gc是启用与垃圾收集相关的所有日志条目的快捷方式。其中,gc:file=<filename>是指将GC日志输出到指定的文件中。

应用GC停止时间和应用GC并发时间

使用-XX:+PrintGCApplicationConcurrentTime和-XX:PrintGCApplicationStoppedTime,HotSpot VM可以报告应用在安全点操作之间的运行时间,以及阻塞Java线程的时间。利用这两个命令行选项观察安全点操作有助于理解和量化延迟对JVM的影响,也可以用来辨别是JVM安全点操作还是应用程序引入的延迟。命令使用示例如下:

java -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -jar hello-world.jar

Java堆调优

HotSpot VM根据对象存活周期的不同,将内存划分三部分:老年代(Tenured Generation)和新生代(Young Generation)、永久代(Permanet Generation)。其中,老年代和新生代组合了堆空间,而永久代则在堆空间之外。在新生代中,存放新分配的对象,在老年代中,存放旧的或长期存活或大的对象,在永久代中,存放JVM加载的类元数据(如类的结构信息、常量池等)、类静态变量,等。在Java 8中,永久代被元空间所取代,元空间使用本地内存,可以动态扩展。HotSpot VM堆布局如下所示:
请添加图片描述

堆大小

-Xmx和-Xms设置堆的初始值和最大值。其中-Xmx设定了初始值及最小值,-Xmx设定了最大值。当-Xms指定的值小于-Xmx的值时,新生代及老年代空间大大小会根据应用的需求动态的扩展或缩减。对于吞吐量和延迟关注的Java应用应将-Xms和-Xmx设定为同一值。这样,就不会因为新生代和老年代空间的动态的扩展或缩减触发Full GC,从而降低应用的吞吐量和更长的延迟。如果-Xms指定的值比-Xmx的值大,那么会导致JVM在启动时就会因为无法满足内存分配要求而失败,并可能抛出一个错误。所以业务环境上,不可能存在-Xms值大于-Xmx值的情况。此外,如果堆的初始值设置过小,可能会导致应用在启动的时候进行扩容,从而延长启动时间。在需要优化启动时间的时候,可以观察启动期间是否有堆扩容动作。
HotSpot VM不指定Java堆的大小时,会根据物理机或虚拟机的物理内存或分配的物理内存的大小来计算默认的堆大小。具体的计算方式可能因JVM版本和操作系统而略有不同,但大致遵循如下规则:
(2) 对于64位JVM,默认的堆大小会根据物理内存的大小来计算。在物理内存小于192MB时,JVM的初始和最大堆大小通常为物理内存的一半。当物理内存大于192MB但小于1GB时,JVM的最大堆大小通常为物理内存的1/4。而当物理内存大于或等于1GB时,JVM的最大堆大小可能会根据JVM版本和操作系统的不同而有所变化,但通常会限制在一个合理的范围内,以避免过度消耗系统资源。
一般情况下,默认的堆大小不能够充分的利用物理内存,所以均需要手动设置JVM的堆大小。通常建议将JVM的最大堆大小设置为物理内存的1/4至1/2之间,但这只是一个大致的指导原则,具体设置需要根据实际情况进行调整。JVM除了堆空间会占用内存,栈空间、系统其他资源也会消耗内存,所以不建议把JVM的堆设置过大。应该在保证系统正常运行、满足业务需要、充分测试等前提下,合理设置JVM的堆大小。不建议JVM的堆最大值大于物理内存的80%。举例来说,对于物理内存为2GB的环境来说,如果当前环境,主要的业务进程就是Java应用,那么预留400MB的空间已经足够其他对象或进程使用,在经过充分测试后,可以设置Java堆的最大值为1600MB。
设置堆大小的示例命令如下:

java -Xmx1g -Xms512m -jar hello-world.jar

上述命令中,设置堆的最小值为512MB,堆的最大值为1GB。

新生代

在调优延迟或响应时间时,Minor GC的持续时间会影响应用的平均停滞时间,Minor GC的执行频率会影响平均停滞的发生频率。根据垃圾收集的统计数据、Minor GC的持续时间和频率可以确定新生代空间的大小。Minor GC需要的时间与新生代中可访问的对象数直接相关。通常情况下,新生代空间越小,Minor GC持续的时间越短。不考虑这对于Minor GC持续时间的影响,减少新生代空间又会增大Minor GC的频率。这是因为以同样的对象分配频率,较小的新生代空间在很短时间内就会被填满,增大新生代空间可以减少Minor GC的频率。
分析GC数据时,如果发现Minor GC的间隔时间较长,修正的方法是减少新生代空间。如果Minor GC频率太高,修正的方法是增加新生代空间。
计算平均持续时间和频率时,Minor GC的次数越多,平均持续时间及频率的统计也就越准确。另外,使用应用运行于稳定阶段时的Minor GC的值也是非常重要的。
调整新生代的示例命令如下:

# 新生代固定为256MB
java -Xms512m -Xmx1024m -Xmn256m -jar hello-world.jar
# 新生代动态调整,且最小值为128MB,最大值为256MB
java -Xms512m -Xmx1024m -XX:NewSize=128m -XX:MaxNewSize=256m -jar hello-world.jar
# 新生代固定比例,NewRatio=3,表示新生代和老年代的大小比例就是1:3,也即新生代占1/4
java -Xms512m -Xmx1024m -XX:NewRatio=3 -jar hello-world.jar

HotSpot VM中,支持同时设置-Xmn以及-XX:NewSize或-XX:MaxNewSize以及-XX:NewRatio。-Xmn的优先级最高,其次是-XX:NewSize、-XX:MaxNewSize,最后是-XX:NewRatio。注意,不建议同时使用功能有重叠的命令,这会给后面的维护带来不必要的误导。推荐使用-Xmn给新生代设置一个固定的大小。

老年代

在调优延迟或响应时间时,Full GC的持续时间会影响应用的最大停顿时间,Full GC的执行频率会影响应用的最大停滞发生的频率。发生于稳定态的Full GC的持续时间是应用的最差Full GC停顿时间。如果多个Full GC在稳定态发生,就按平均最差停顿时间计算。取样的数据越多,预测的结果越准确。
从老年代中减去活跃数据的大小可以得到可用老年代空间大小。需要多长时间才能填满老年代的空闲空间取决于新生代到老年代的提升率。提升率可以依据老年代空间占用的增长量以及每次Minor GC后新生代的空间占用计算得出。老年代的空间占用情况可以通过Minor GC之后Java堆的占用情况减去同一次Minor GC后新生代的空间占用得到。
如果预期或观测到Full GC的频率已经远不能达到应用的最差Full GC频率要求,就应该增大老年代空间的大小。这个方法可以帮助降低Full GC的评率。增大老年代空间时,注意保持新生代空间大小恒定。
如果修改老年代空间大小后,只观察到Full GC,很可能是老年代与新生代空间大小失去了平衡,导致应用只进行Full GC。这一情况通常源于即使老年代经过Full GC,仍不足以容纳所有从新生代提升的对象。标识老年代空间不够大的一个线索是每次Full GC之后,老年代几乎没有任何空间被回收,而新生代总有大量的对象占用空间。当老年代没有足够的空间接纳从新生代提升的对象时,这些对象机会被"退还"到新生代空间中。
JVM不支持直接调整老年代的大小,而是通过Java堆大小减去新生代的大小,间接的计算出老年代的大小。这里不在补充命令示例。

永久代或元空间

永久代用来存放JVM加载的类元数据(如类的结构信息、常量池等)、类静态变量,等。在Java 8及更高的版本中,永久代被元空间所取代,元空间使用本地内存,可以动态扩展。永久代空间大小设置示例命令如下:

java -XX:PermSize=64m -XX:MaxPermSize=256m -jar hello-world.jar

为了解决永久代的大小是有限的问题,Java 8引入了元空间。元空间使用本地内存(native memory)来存储类的元数据,其大小可以根据需要进行动态调整。这大大减少了类加载过程中的内存限制,并提高了应用程序的灵活性。元空间大小设置示例命令如下:

java -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -jar hello-world.jar

默认情况下,元空间的大小是没有上限的,即它的大小受限于机器的物理内存。然而,为了避免因元空间无限增长而导致的内存溢出问题,需要设置一个合理的最大值。

调整Survivor空间的容量

调整Survivor空间容量一个应该谨记于心的重要原则:调整Survivor空间容量时,如果新生代空间不变,增大Survivor空间会减少Eden空间;而减少Eden空间会增加Minor GC的频率。因此,为了同时满足应用Minor GC频率的要求,就需要增大当前新生代的空间;即增大Survivor空间大小时,Eden空间的大小应保持不变。如果可以增大Minor GC的频率,则可以选择用一部分Eden空间来增大Survivor空间。如果内存足够,相对于减少Eden空间,增大新生代大小通常是更好的选择。保持Eden空间不变,Minor GC的频率就不会因为Survivor空间增大而发生变化。再次提醒,减少Eden空间会导致更频繁的Minor GC。因为调整Survivor空间是通过增加新生代实现,所以可以参考新生代的调整命令。此外,如果需要调整新生代中Eden和Survivor的比例,可以使用如下的示例命令:

java -Xms1024m -Xmx1024m -Xmn256m -XX:SurvivorRatio=8 -jar hello-world.jar

上述示例中,SurvivorRatio参数决定了Eden区与单个Survivor区之间的大小比例。这里设置SurvivorRatio为8,所以Eden区的大小将是单个Survivor区大小的8倍。
调整SurvivorRatio的值时,重点关注Survivor值缩小的场景。尽管调大Survivor空间会带来不必要的资源浪费,但是执行调大操作时,基本上都是发现Survivor不足时才去调大。所以应重点关注Survivor空间过小的场景。如果Survivor区太小,可能会导致对象在Survivor区之间频繁地复制(即Survivor溢出到老年代),这可能会增加Minor GC的频率和持续时间,并可能导致不必要的对象晋升到老年代。

调整晋升阈值

HotSpot VM在每次Minor GC时,都会计算晋升阈值以决定何时对一个对象进行提升。或者说,晋升阈值就是对象的年龄。一个对象的年龄就是它所经历的Minor GC次数。对象首次分配时,其年龄是0。下一次Minor GC之后,如果该对象还在新生代,其年龄加一,以此类推。新生代中年龄大于HotSpot VM计算出的晋升阈值的对象被提升到老年代。晋升阈值计算的依据是Minor GC之后新生代要容纳的可达对象需要的空间大小及目标Survivor空间占用的空间大小(如果Survivor空间过小,一次Minor GC可能会导致Survivor溢出,溢出的对象将直接提升到老年代)。可以使用-XX:MaxTenuringThreshold=<n>指定在对象年龄超过阈值后,将其提升到老年代。在Open JDK的版本中,MaxTenuringThreshold的默认值是15。但是,这个默认值可能会在不同的JVM实现或版本中有所不同。可以使用-XX:+PrintTenuringDistribution选项来启动JVM。这个选项会在每次Minor GC之后打印出Survivor区中对象的年龄分布信息,同时也会显示当前的MaxTenuringThreshold设置值。晋升阈值示例命令如下:

java -Xms1024m -Xmx1024m -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution -jar hello-world.jar

不建议将晋升阈值设置过小,这会导致最近分配的对象很快提升到老年代,同时造成老年代空间的迅速增大,引起频繁的Full GC。同时,也不建议将晋升阈值设置为远大于实际可能的最大值。这会造成对象长期存在于Survivor空间,直到最后溢出。一旦溢出,对象将会被全部提升到老年代,从而造成短期存在对象在长期存在对象之前被提升到老年代,严重影响对象老化机制的有效性。

禁用显式的垃圾收集

Java提供System.gc()接口,这样开发人员就可显式地出发垃圾收集。注意,这个方法并不会直接执行垃圾回收,而是向JVM发出一个建议,让JVM尝试回收不再使用的对象以释放内存。所以,调用System.gc()并不保证垃圾回收会立即执行,因为JVM有自己的垃圾回收策略和调度机制。JVM会根据其内部的算法和当前的系统状态来决定何时执行垃圾回收。
可以使用-XX:+DisableExplicitGC命令行选项通知HotSpot VM忽略显式的System.gc()调用。示例命令如下:

java -XX:+DisableExplicitGC -jar hello-world.jar

禁用显式的垃圾收集时应该慎重,它可能会对应用的性能造成较大的影响。还有可能出现这样场景,开发人员需要及时的对对象引用做处理,但与之对应的是垃圾收集却跟不上其节奏。建议除非有非常明确的理由,否则不要轻易地禁用显式的垃圾收集。与此同时,也建议只有在明确理由下才能在应用中使用System.gc()。
注意,禁用了System.gc(),JVM仍然会根据其内部算法和需要自动进行垃圾回收。这个参数只是禁用了对垃圾回收的显式请求,而不是禁用垃圾回收机制。

Java线程调优

Java是多线程语言,天然支持多线程处理。在进行多线程处理时,会遇到线程的堆栈大小不符合业务需求、线程竞争等问题。

Java线程的栈大小

对于运行在线程栈上的线程来说,会遇到栈溢出(StackOverflowError)的问题。除了死循环导致的栈溢出外,还有一种情况是线程栈过小,不符合业务的需求(递归深度或大量局部变量)。调整线程栈大小的示例命令如下:

java -Xss512k -jar hello-world.jar

Xss参数用来指定每个线程的虚拟机栈大小,直接影响线程虚拟机栈的栈帧数量,即方法调用的层级深度。Xss参数指定的大小理论上会影响JVM能够生成的最大线程数量,但实际上这个数量更多地受到操作系统的最大线程数配置、物理内存大小等因素的限制。不同Java版本中,Xss的默认值不同。

Java线程间锁竞争

Java支持多线程编程,对于多线程来说,无法保证线程之间不存在锁竞争或死锁等问题。在进行Java应用调优时,如果是多线程应用,且测试的场景使用到了多线程和锁,则有必要监控线程信息。可以使用JDK的jstack工具或主流的Java应用分析工具(如Arthas)抓取线程转储信息。
Java线程间锁竞争虽然不属于JVM调优范畴,但是和JVM架构息息相关,这里作为拓展内容做简单地讨论。

参考

《Java性能优化权威指南》 Charlie Hunt, Binu John 著, 柳飞, 陆明刚 译
https://segmentfault.com/a/1190000044547802 JVM 8 调优指南:如何进行JVM调优,JVM调优参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/324382.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【问题分析】锁屏界面调起google语音助手后壁纸不可见【Android 14】

1 问题描述 为系统和锁屏分别设置两张不同的壁纸&#xff0c;然后在锁屏界面长按Power调起google语音助手后&#xff0c;有时候会出现壁纸不可见的情况&#xff0c;如以下截图所示&#xff1a; 有的时候又是正常的&#xff0c;但显示的也是系统壁纸&#xff0c;并非是锁屏壁纸…

Map按value降序并统计

package com.ldj.cloud.user.demo;import java.util.*;/*** User: ldj* Date: 2024/5/11* Time: 10:03* Description: map按value降序*/ public class Tr {public static void main(String[] args) {ArrayList<String> list new ArrayList<>();list.add("a&q…

纯血鸿蒙APP实战开发——阅读翻页方式案例

介绍 本示例展示手机阅读时左右翻页&#xff0c;上下翻页&#xff0c;覆盖翻页的功能。 效果图预览 使用说明 进入模块即是左右翻页模式。点击屏幕中间区域弹出上下菜单。点击设置按钮&#xff0c;弹出翻页方式切换按钮&#xff0c;点击可切换翻页方式。左右翻页方式可点击翻…

【前端】JavaScript的WebAPI | DOM | 获取元素 | 事件 | 操作元素 | 操作节点

文章目录 [toc] JavaScript的WebAPI一、DOM1.DOM树2.获取元素1.querySelector2.querySelectorAll 3.事件事件三要素点击事件键盘事件 4.操作元素获取/修改元素内容获取/修改元素属性获取/修改表单属性获取/修改样式属性行内样式操作类名样式操作 5.操作节点新增节点删除节点 Ja…

EasyRecovery数据恢复软件2024最新免费无需激活版下载

EasyRecovery数据恢复软件是一款功能强大、操作简便的数据恢复工具&#xff0c;旨在帮助用户解决各种数据丢失问题。无论是由于误删除、格式化、磁盘损坏还是其他原因导致的数据丢失&#xff0c;EasyRecovery都能提供有效的恢复方案。以下是对EasyRecovery软件功能的详细介绍。…

XWiki 服务没有正确部署在tomcat中,如何尝试手动重新部署?

1. 停止 Tomcat 服务 首先&#xff0c;您需要停止正在运行的 Tomcat 服务器&#xff0c;以确保在操作文件时不会发生冲突或数据损坏&#xff1a; sudo systemctl stop tomcat2. 清空 webapps 下的 xwiki 目录和 work 目录中相关的缓存 删除 webapps 下的 xwiki 目录和 work …

IP报文在设备间传递的封装过程

IP报文传递过程 1、PC1访问PC2报文传递过程1.1、PC1准备数据请求报文封装1.2、PC1准备ARP请求报文1.3、PC2准备ARP响应报文1.4、PC1完成数据请求报文封装 2、PC1访问PC3报文传递过程2.1、PC1准备数据请求报文封装2.2、PC1准备获取网关MAC地址的ARP请求报文2.3、网关准备ARP响应…

Github2024-05-10开日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-05-10统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目4TypeScript项目4JavaScript项目1Lua项目1C项目1Rust项目1Dart项目1 RustDesk: 用Rust编写的开源远…

【Linux】进程间通信之共享内存

&#x1f916;个人主页&#xff1a;晚风相伴-CSDN博客 &#x1f496;如果觉得内容对你有帮助的话&#xff0c;还请给博主一键三连&#xff08;点赞&#x1f49c;、收藏&#x1f9e1;、关注&#x1f49a;&#xff09;吧 &#x1f64f;如果内容有误的话&#xff0c;还望指出&…

【Linux系统编程】第十六弹---冯诺依曼体系结构与操作系统

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、冯诺依曼体系结构 2、操作系统原理 2.1、什么是操作系统&#xff1f; 2.2、用图解释操作系统 2.3、理解操作系统 总结 …

QT的TcpServer

Server服务器端 QT版本5.6.1 界面设计 工程文件&#xff1a; 添加 network 模块 头文件引入TcpServer类和TcpSocket&#xff1a;QTcpServer和QTcpSocket #include <QTcpServer> #include <QTcpSocket>创建server对象并实例化&#xff1a; /*h文件中*/QTcpServer…

NAND Flash 与 NOR Flash间的区别

非易失性存储器是一种即使未通电也能保持其内容的存储器。非易失性存储器可以有不同的形式: ROM – 只读存储器&#xff0c;数据写入一次&#xff0c;允许多次读取访问。 PROM – 可编程只读存储器&#xff0c;数据写入一次&#xff08;不是在制造过程中&#xff0c;而是以后的…

【论文速读】| LLM4FUZZ:利用大语言模型指导智能合约的模糊测试

本次分享论文&#xff1a;LLM4FUZZ: Guided Fuzzing of Smart Contracts with Large Language Models 基本信息 原文作者&#xff1a;Chaofan Shou, Jing Liu, Doudou Lu, Koushik Sen 作者单位&#xff1a;加州大学伯克利分校&#xff0c;加州大学欧文分校&#xff0c;Fuzz…

15 华三华为链路聚合综述

1 链路聚合简介 以太网链路聚合通过将多条以太网物理链路捆绑在一起形成一条以太网逻辑链路&#xff0c;实现增加链路带宽的目的&#xff0c;同时这些捆绑在一起的链路通过相互动态备份&#xff0c;可以有效地提高链路的可靠性。 2 成员端口的状态 聚合组内的成员端口具有以下…

2024年,Web开发新趋势!

随着我们迈入新的一年&#xff0c;现在正是审视2024年网页开发领域开始流行哪些趋势的绝佳时机。回顾2023年的一系列更新&#xff0c;以下是来年一些热门话题的概览。 自主托管有回归的趋势 近些年&#xff0c;自主托管一直是网页开发者和公司托管其应用程序的默认方式。开发…

蓝桥杯13届JAVA A组 国赛

​​​​​​​ package 蓝桥杯国赛; // 贪心选个数最少的进行摆 // 2:1 ,3:1, 4:1,5 : 3,6:3,7:1 // 选 1&#xff0c;7&#xff0c;4&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;9 // 然后都选满10个 public class 火彩棒数字 {public static void main(String[] a…

游戏行业被攻击的原因、攻击种类及合适的服务器

很多游戏刚上线没多久就频繁遭到同行恶意攻击。在相关数据报告中&#xff0c;2023年上半年遭受DDoS攻击的行业中&#xff0c;游戏行业占到40%&#xff0c;而且攻击方式、攻击频率、攻击峰值呈明显上升趋势。很多充满创意的游戏开发公司刚才开发上线一个很有特色的产品&#xff…

安卓实现视频录制与显示和翻转摄像头

权限&#xff1a; <!-- 相机权限 --> <uses-featureandroid:name"android.hardware.camera"android:required"false" /> <uses-permission android:name"android.permission.CAMERA" /><!-- 录音权限&#xff08;包括麦克…

Centos 7.9 配置VNCServer实现远程vnc连接

文章目录 1、Centos安装图形界面1.1、安装X Windows System图形界面1.2、安装GNOME图形界面 2、VNC SERVER配置2.1、VNC SERVER安装2.2、VNC SERVER配置1&#xff09;创建vnc配置文件2&#xff09;修改配置文件内容3&#xff09;完整配置文件参考 2.3、设置vnc密码2.4、配置防火…

网络编程套接字和传输层tcp,udp协议

认识端口号 我们知道在网络数据传输的时候&#xff0c;在IP数据包头部有两个IP地址&#xff0c;分别叫做源IP地址和目的IP地址。IP地址是帮助我们在网络中确定最终发送的主机&#xff0c;但是实际上数据应该发送到主机上指定的进程上的&#xff0c;所以我们不仅要确定主机&…