Java基础之JVM对象内存分配机制简介

一 对象内存分配

1.1 运行时数据区域 

1.2 常见java应用启动JVM参数:

  •  -Xss:每个线程的栈大小(单位kb)
  • -Xms:堆的初始大小,默认物理内存的1/64,示例:-Xms:4g -Xms:10m
  • -Xmx:堆的最大可用大小,默认物理内存的1/4
  • -Xmn:新生代大小
  • -XX:NewRatio:默认2,表示新生代占老年代的1/2,占整个堆内存的1/3
  • -XX:SurvivorRatio:默认8,表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存

1.3 关于元空间的JVM参数:

  • -XX:MaxMetaspaceSize:元空间最大大小,默认-1,即不限制,即受限于本地内存大小;
  • -XX:MetaspaceSize:元空间触发FullGC的初始阈值(元空间无固定初始大小),单位:字节,默认是21M左右,元空间使用大小达到该值会触发FullGC进行类型卸载,同时jvm收集器会对该值进行调整:
    • 如果如果释放了大量空间,适当降低该值;
    • 如果释放了很少的空间,且元空间大小,未超过-XX:MaxMetaspaceSize,适当提高-XX:MetaspaceSize值;

由于调整元空间大小需要FullGC,这是非常昂贵的操作,如果应用在启动的时候发生大量的FullGC,通常是由于元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将-XX:MetaspaceSize -XX:MaxMetaspaceSize设置成一样大小,并且初始值比默认值要大,比如对于8G物理内存的机器,可以将元空间大小设置为256M、512M;

 1.4 StackOverflowError问题

源码:

public class StackOverflowHelper {static int count;static void doBusiness(){count++;doBusiness();}/*** 启动jvm参数 -Xms256m -Xmx256m -Xss128k(默认1M)* @param args*/public static void main(String[] args) {try{doBusiness();}catch (Exception e){System.out.println(e);}}
}

 运行结果:

 java -Xms256m -Xmx256m -Xss128k com.ddu.jvm.StackOverflowHelper
Exception in thread "main" java.lang.StackOverflowErrorat com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:6)at com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:7)at com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:7)at com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:7)at com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:7)at com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:7)at com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:7)at com.ddu.jvm.StackOverflowHelper.doBusiness(StackOverflowHelper.java:7)

总结:-Xss设置越小,说明一个线程栈里能分配的栈帧数量就越少,但是对于JVM整体来说可以开启的线程数就会更多; 

二 内存分配场景

2.1 对象在Eden区分配

一般情况下,新对象会在新生代的eden区分配内存空间,但Eden区没有足够的空间进行分配时,虚拟机会发起一次MinorGC;

  • MinorGC/YoungGC:指发生在新生代的垃圾收集动作;MinorGC非常频繁,回收速度一般比较快;
  • MajorGC/FullGC:一般回收老年代、年轻代、方法区的垃圾,MajorGC的速度一般会比MinorGC慢10倍以上;
  • 示例1:

  • package com.ddu.jvm;public class GcHelper {public static void main(String[] args) {byte[] data1, data2, data3, data4, data5, data6;data1 = new byte[1024 * 1000 * 10 * 6];}
    }
    java -Xms256M -Xmx256M -XX:+PrintGCDetails com.ddu.jvm.GcHelper
    HeapPSYoungGen      total 76288K, used 63932K [0x00000000fab00000, 0x0000000100000000, 0x0000000100000000)eden space 65536K, 97% used [0x00000000fab00000,0x00000000fe96f250,0x00000000feb00000)from space 10752K, 0% used [0x00000000ff580000,0x00000000ff580000,0x0000000100000000)to   space 10752K, 0% used [0x00000000feb00000,0x00000000feb00000,0x00000000ff580000)ParOldGen       total 175104K, used 0K [0x00000000f0000000, 0x00000000fab00000, 0x00000000fab00000)object space 175104K, 0% used [0x00000000f0000000,0x00000000f0000000,0x00000000fab00000)Metaspace       used 2605K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 284K, capacity 386K, committed 512K, reserved 1048576K
    

    总结:当前示例中Eden区占用比例达到97%,基本已经被占满;

  • 示例2:

在【实例1】的基础上继续分配内存;

package com.ddu.jvm;public class GcHelper {public static void main(String[] args) {byte[] data1, data2, data3, data4, data5, data6;data1 = new byte[1024 * 1000 * 10 * 6];data2 = new byte[1024 * 1000 * 8];}
}
java -Xms256M -Xmx256M -XX:+PrintGCDetails com.ddu.jvm.GcHelper
[GC (Allocation Failure) [PSYoungGen: 62621K->784K(76288K)] 62621K->60792K(251392K), 0.0305527 secs] [Times: user=0.00 sys=0.02, real=0.03 secs] 
HeapPSYoungGen      total 76288K, used 10723K [0x00000000fab00000, 0x0000000100000000, 0x0000000100000000)eden space 65536K, 15% used [0x00000000fab00000,0x00000000fb4b4c80,0x00000000feb00000)from space 10752K, 7% used [0x00000000feb00000,0x00000000febc4020,0x00000000ff580000)to   space 10752K, 0% used [0x00000000ff580000,0x00000000ff580000,0x0000000100000000)ParOldGen       total 175104K, used 60008K [0x00000000f0000000, 0x00000000fab00000, 0x00000000fab00000)object space 175104K, 34% used [0x00000000f0000000,0x00000000f3a9a010,0x00000000fab00000)Metaspace       used 2605K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 284K, capacity 386K, committed 512K, reserved 1048576K

现象:

  • 发生了MinorGC
  • from区被占用了部分空间
  • 有对象转移至老年代 ,ParOldGen used 60008K,说明data1被转移至老年代;

总结:

  1. 由【示例1】可知,data1分配完内存之后,Eden区已经占用达97%,继续在Eden区尝试分配data2,因为Eden剩余空间无法放下data2因此触发MinorGC,
  2. MinorGC期间JVM发现Survivor区无法分配存储data1,因此只好把新生代的对象data1提前转移到老年代中去,老年代上的空间足够存放data1,所以不会触发FullGC;
  3. 执行完MinorGC之后,后面分配的对象如果能够全部放在Eden区的话,还是会在Eden区分配;

示例3:

package com.ddu.jvm;public class GcHelper {public static void main(String[] args) {byte[] data1, data2, data3, data4, data5, data6;data1 = new byte[1024 * 1000 * 10 * 6];data2 = new byte[1024 * 1000 * 8];data4 = new byte[1024 * 1000];data5 = new byte[1024 * 1000];data6 = new byte[1024 * 1000];}
}

 运行结果:

java -Xms256M -Xmx256M -XX:+PrintGCDetails com.ddu.jvm.GcHelper
[GC (Allocation Failure) [PSYoungGen: 62621K->800K(76288K)] 62621K->60808K(251392K), 0.0286915 secs] [Times: user=0.02 sys=0.02, real=0.03 secs]
HeapPSYoungGen      total 76288K, used 12739K [0x00000000fab00000, 0x0000000100000000, 0x0000000100000000)eden space 65536K, 18% used [0x00000000fab00000,0x00000000fb6a8c38,0x00000000feb00000)from space 10752K, 7% used [0x00000000feb00000,0x00000000febc8030,0x00000000ff580000)to   space 10752K, 0% used [0x00000000ff580000,0x00000000ff580000,0x0000000100000000)ParOldGen       total 175104K, used 60008K [0x00000000f0000000, 0x00000000fab00000, 0x00000000fab00000)object space 175104K, 34% used [0x00000000f0000000,0x00000000f3a9a010,0x00000000fab00000)Metaspace       used 2605K, capacity 4486K, committed 4864K, reserved 1056768Kclass space    used 284K, capacity 386K, committed 512K, reserved 1048576K

现象:

  • 老年代已占用空间未发生变化;

总结:

  •  当前示例充分证明了【示例2的总结3】执行完MinorGC之后,后面分配的对象如果能够全部放在Eden区的话,还是会在Eden区分配;

2.2 Eden:Survivor0:Survivor1

大量对象分配在Eden区,Eden区慢了后会触发MinorGC,可能99%以上的对象会变成垃圾而被回收掉,而剩余存活的对象会被挪到空的Survivor0区,下次Eden区满后会触发MinorGC,把Eden区+Survivor0区中存活的对象复制到Survivor区,并Eden区和Survivor区垃圾回收,因此新生代的对象大部分是朝生夕死,存活时间比较多,所以JVM默认的8:1:1比例很合适,原则:让Eden区尽量大,Survivor区足够用就可以;

其中Eden:Survivor0:Survivor的比例会根据UseAdpativeSizePolicy参数决定是否自动调整;

  • -XX:+UseAdpativeSizePolicy:动态自动调整Eden:Survivor的比例;默认开启;

2.3 大对象直接进入老年代

大对象是需要大量连续内存空间的对象(比如数组、字符串),JVM参数

-XX:PretenureSizeThreshold可以设置判断大对象的大小阈值,当新对象大小超过设置阈值会跳过新生代分配直接在老年代内存进行分配;但是当前参数只有在Serial和ParNew两类收集器下才能生效;例如:

-XX:PretenureSizeThreshold=1000000 -XX:UseSerialGC

为什么需要设置大对象呢?

  • 为了避免为大对象分配内存时复制操作降低了垃圾回收效率; 

2.4 长期存活的对象进行老年代

虚拟机采用了分代收集的思想来管理内存,那么内存收回时就必须呀能识别那些对象应该分配在新生代,哪些对象应该分配在老年代;为什么实现这个功能,虚拟机给每个对象设置了一个对象年龄(age)计数器。

如果对象在Eden区分配之后,经过一次MindorGC后,仍然存活下来了,并且可以被Survivor存储,则将当前对象的对象年龄+1,当对象的年龄增加到一定程度(默认15,CMS收集器默认6,不同的垃圾收集器略微不同),当前对象就会晋升至老年代中,其中可以通过

-XX:MaxTenuringThreshold参数来设置;

2.5 对象动态年龄判断

当前存放对象的Survivor(两个Survivor区域,同一时刻只有一个Survivor区域存储对象)区域,其中一批对象的总大小大于Survivor区域内存大小的50%(-XX:TargetSurvivorRatio可以指定),那么此时大于等于这批对象里面对象年龄最多的所有对象,在MinorGC阶段直接被转移至老年代中;

例如:年龄1+年龄2+年龄n的多个对象占用内存综合超过Survivor区域的50%,此时就会把年龄n(包含n)以上的对象全部转移至老年代;

目的:让可能长期存货的对象尽早进入老年代;

2.6 老年代空间分配担保机制

年轻代进行MinorGC前,JVM会计算老年代剩余可用空间LOC

  1. 如果LOC小于年轻代里现有的所有对象大小之和(包括垃圾对象),进入步骤2
  2. 如果配置了-XX:HandlePromotionFailure(jdk8默认配置),进入步骤3,否则进入步骤4
  3. 判断老年代的剩余可用大小,是否大于之前每一次MinorGC后进入老年代对象的平均大小,是则进入步骤4,否则进入步骤5;
  4. 触发FullGC,针对老年代和新生代一起进行一次垃圾回收,如果回收完之后没有足够的空间存储新对象,此时就会发生OOM
  5. 触发MinorGC,GC之后剩余存活需要移动至老年代的对象大小还是大于老年代剩余可用大小,触发FullGC,如果FullGC后还是没有空间存放新进入的存活对象,此时就会发生OOM;

三 对象栈上分配

  一般情况下,Java中的对象大部分是在堆上进行分配的,当对象没有被引用时,需要依赖GC进行垃圾回收释放内存;如果对象数量比较多,会给GC带来较大的压力,STW时间较长,进而影响系统的整体性能;在某些特殊情况下,经过逃逸分析后发现,一个对象没有逃逸出方法的话,可能当前对象会被优化成栈上分配,也就不需要在堆上分配内存了;

背景

在java的编译提醒中,一个java源码文件变成计算机可执行的机器指令的过程中,需要进过两阶段编译:

  • 第一阶段:把java文件转成class文件;
  • 第二阶段:把class文件转成机器指令;

其中在第二编译阶段,JVM通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解析翻译;经过解释执行,其执行速度会比可执行的二进制字节码程序慢一些,这就是传统的JVM解释器的功能,为了提高整个过程的效率,引入了JIT(即时编译)技术;

标量与聚合量

  • 标量:指一个无法可被继续分解的对象,java中的基本数据类型就是标量。
  • 聚合量:与标量对立的对象就是聚合量,聚合量就是可以被进一步分解的对象;

逃逸基本原理和逃逸状态

分析对象动态作用域,当一个对象在方法内被定义后,它可能会被外部方法引用,例如

  • 对象作为当前方法的返回值被外部调用方法使用或者对象作为参数传递给其他方法使用,这种称之为方法逃逸;
  • 可能被外部线程访问到,比如赋值给可以在其他线程中访问的实例变量,这种称之为线程逃逸;

不逃逸=>方法逃逸=>线程逃逸,称为对象由低到高的不同逃逸程度;逃逸大概分类如下:

  • 全局逃逸:对象逃逸出当前方法和线程。例如存储在静态变量中的对象、存储在转义对象的变量中、作为当前方法的结果返回的对象;
  • 参数逃逸:对象做为参数传递或由参数引用,在调用期间不会全局逃逸,这个状态是通过分析被调用方法的字节码来确定的;
  • 没有逃逸:对象只在方法内部使用,没有发生逃逸,该对象是一个标量可替换对象,这意味着当前变量可以进行栈上分配;

逃逸分析

代码:

public class UserEscapeAnalysisHelper {public static void main(String[] args) throws InterruptedException {long start = System.currentTimeMillis();for (int i = 0; i < 100000000; i++) {alloc();}System.out.println(System.currentTimeMillis()-start);Thread.sleep(1000 * 100000);}private static void alloc(){User user = new User();}static class User{}
}

上述代码,使用for循环,在代码中创建1亿User对象。其中alloc()方法中定义了User对象,但是没有在方法外部引用它,也就是说这个对象并不会逃逸到alloc方法外部,开启逃逸分析情况下,经过JIT的逃逸分析,可以对内存分配进行优化;

  • 逃逸分析和标量替换必要同时开启,JVM才能进行内存分配的优化,自JDK8开始,默认开启逃逸分析和标量替换;

具体演示过程如下:

涉及到的命令如下:

命令        说明
-XX:+DoEscapeAnalysis开启逃逸分析(JDK8起默认开启)
-XX:-DoEscapeAnalysis关闭逃逸分析
-XX:+PrintEscapeAnalysis打印逃逸分析明细
-XX:+EliminateAllocations开启标量替换
-XX:-EliminateAllocations关闭标量替换
-XX:+PrintEliminateAllocations打印标量替换明细
-XX:+PrintGC打印gc过程

关闭逃逸分析和标量替换

java -Xmx4g -Xms4g -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+PrintGC com.ddu.jvm.UserEscapeAnalysisHelper

在关闭逃逸分析的情况下,堆中总共创建了340w个实例,虽然alloc方法中创建的User对象没有逃逸到方法外部,但是还是会被分配到堆内存中,也就是说:如果没有JIT编译器优化,没有逃逸分析技术,正常情况下就应该是分配到堆内存中; 

开启逃逸分析和标量替换

java -Xmx4g -Xms4g -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+PrintGC com.ddu.jvm.UserEscapeAnalysisHelper

 开启了逃逸分析,在jmap打印内存情况下看,在堆中只有11w个User对象,也就是说经过JIT优化之后,堆内存中分配的对象数量,从340w降到了11w。


总结:栈上分配依赖于逃逸分析和标量替换;

四 垃圾对象判定算法

4.1 引用计数法

4.2 可达性分析算法

五 常见的引用类型

java的引用类型一般分四种:强引用、软引用、弱引用、虚引用;

5.1 强引用

5.2 软引用

5.3 弱引用

5.4 虚引用

5.5 finalize()方法最终判定对象是否存活

5.6 如何判定一个类是无用的类

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

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

相关文章

水库大坝安全白蚁监测系统解决方案

一、系统背景 白蚁作为河岸生态系统中的重要病害&#xff0c;不仅会导致水库大坝外部环境发生改变&#xff0c;甚至会引发水库大坝破坏&#xff0c;进而导致自身结构失去稳定性&#xff0c;严重影响水库大坝的正常运行。因此&#xff0c;治理水库大坝白蚁是确保水库大坝工程顺利…

HTTP与HTTPS 对比,区别详解(2024-04-25)

一、简介 HTTP&#xff08;超文本传输协议&#xff0c;Hypertext Transfer Protocol&#xff09;是一种用于从网络传输超文本到本地浏览器的传输协议。它定义了客户端与服务器之间请求和响应的格式。HTTP 工作在 TCP/IP 模型之上&#xff0c;通常使用端口 80。 HTTPS&#xf…

【Hadoop】- MapReduce YARN 初体验[9]

目录 提交MapReduce程序至YARN运行 1、提交wordcount示例程序 1.1、先准备words.txt文件上传到hdfs&#xff0c;文件内容如下&#xff1a; 1.2、在hdfs中创建两个文件夹&#xff0c;分别为/input、/output 1.3、将创建好的words.txt文件上传到hdfs中/input 1.4、提交MapR…

区块链技术与应用学习笔记(8-9节)——北大肖臻课程

目录 8.挖矿 对于全节点和轻节点思考问题&#xff1f; ①全节点在比特币的主要作用&#xff1f; ②挖矿时当监听到别人已经挖出区块并且延申了最长合法链此时应该立刻放弃当前区块在 本地重新组装一个指向最后这个新合法区块的候选区块&#xff0c;重新开始挖矿。节点这么做…

「React Native」为什么要选择 React Native 作为的跨端方案

文章目录 前言一、常见因素二、举个栗子2.1 项目背景2.2 为什么选择 React Native2.3 项目实施2.4 成果总结 前言 没有完美的跨端技术&#xff0c;只有适合的场景。脱离适用场景去谈跨端技术没有什么意义。 一、常见因素 共享代码库&#xff1a; React Native 允许开发者编写…

OmniPlan Pro for Mac v4.8.0中文激活版 项目流程管理工具

OmniPlan Pro for Mac是一款功能强大的项目管理软件&#xff0c;它以其直观的用户界面和丰富的功能&#xff0c;帮助用户轻松管理各种复杂的项目。 OmniPlan Pro for Mac v4.8.0中文激活版 通过OmniPlan Pro&#xff0c;用户可以轻松创建任务&#xff0c;设置任务的开始和结束时…

毕业撒花 流感服务小程序的设计与实现

目录 1.1 总体页面设计 1.1.1 用户首页 1.1.2 新闻页面 1.1.3 我的页面 1.1.5 管理员登陆页面 1.1.6 管理员首页 1.2 用户模块 1.2.1 体检预约功能 1.2.2 体检报告功能 1.2.4 流感数据可视化功能 1.2.5 知识科普功能 1.2.6 疾病判断功能 1.2.7 出示个人就诊码功能 …

系统安全测试要怎么做?

进行系统安全测试时&#xff0c;可以按照以下详细的步骤进行&#xff1a; 1、信息收集和分析&#xff1a; 收集系统的相关信息&#xff0c;包括架构、部署环境、使用的框架和技术等。 分析系统的安全需求、威胁模型和安全策略等文档。 2、威胁建模和风险评估&#xff1a; …

【VUE】Vue中实现树状表格结构编辑与版本对比的详细技术实现

Vue中实现树状表格结构编辑与版本对比的详细技术实现 在Vue中&#xff0c;创建一个可编辑的树状表格并实施版本对比功能是一种需求较为常见的场景。在本教程中&#xff0c;我们将使用Vue结合Element UI的el-table组件&#xff0c;来构建一个树状表格&#xff0c;其中包含添加、…

codeforce#933 题解

E. Rudolf and k Bridges 题意不讲了&#xff0c;不如去题干看图。 传统dp&#xff0c;每个点有两个选择&#xff0c;那么建桥要么不建。需要注意的是在状态转移的时候&#xff0c;桥是有长度的&#xff0c;如果不建需要前d格中建桥花费最少的位置作为状态转移的初态。 #incl…

与Apollo共创生态:Apollo7周年大会自动驾驶生态利剑出鞘

前言 4月22日&#xff0c;百度Apollo在北京车展前夕举办了以“破晓•拥抱智变时刻”为主题的智能汽车产品发布会&#xff0c;围绕汽车智能化&#xff0c;发布了智驾、智舱、智图等全新升级的“驾舱图”系列产品。 1、7周年大会 自2013年百度开始布局自动驾驶&#xff0c;201…

Axure RP 9中文激活版:专业原型设计工具mac/win

Axure RP 9是一款由美国Axure Software Solution公司开发的专业原型设计工具。它凭借强大的交互功能和丰富的设计素材&#xff0c;为产品经理、UI设计师、交互设计师等用户提供了高效、便捷的原型设计体验。 Axure RP 9支持快速创建线框图、流程图、原型和规格说明文档&#xf…

c++中的链表list的模拟实现

拖更了半个月&#xff0c;我终于来填c的坑啦。上次我们说的vetcor不知道小伙伴还记得多少呢&#xff1f;今天我们要讲list的模拟实现。 目录 架构结点list表的结构 构造函数尾插push_back()尾删pop_back()计算个数&#xff1a;size()判断空empty()※迭代器问题普通迭代器迭代器…

vue2[黑马笔记]

vue基础 是什么—javascript框架 构建用户界面的前端框架 1.构建用户界面用vue往html页面中填充数据 2.框架现成的解决方案&#xff0c;遵守框架的规范去实现自己的业务功能学习vue 就是学习vue框架中规定的用法vue的指令组件&#xff08;对ul结构的复用&#xff09;&#x…

windows服务启动提示‘服务没有响应控制功能’(mysql启动报错)

在安装mysql的时候&#xff0c;在windows服务项启动 或 使用命令net start mysql 时启动是报错&#xff0c;提示 服务没有响应控制功能 发生原因&#xff1a; Windows10 x64 或 更高的操作系统&#xff0c;有些系统缺少一些组件 解决办法&#xff1a; 1、下载最新的 Microsoft …

CSS详解(一)

1、css工作中使用场景 美化网页&#xff08;文字样式、背景样式、边框样式、盒子模型、定位、动画、&#xff09;&#xff0c;布局页面&#xff08;flex布局、响应式布局、媒体查询&#xff09; 2、CSS 规则 通常由两个主要部分组成选择器和样式声明 2.1选择器 选择器指定了…

制作自己的YOLOv8数据集

制作自己的YOLO8数据集 前言 该数据集的格式参照于coco数据集结构✨ 步骤一&#xff1a;收集图像数据 从互联网上下载公开的数据集&#xff0c;也可以使用摄像头或其他设备自行采集图像&#xff0c;确保你的图像数据覆盖了你感兴趣的目标和场景 步骤二&#xff1a;安装Labe…

正点原子[第二期]ARM(I.MX6U)裸机篇学习笔记-1.2

前言&#xff1a; 本文是来自哔哩哔哩网站上视频“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”的学习笔记&#xff0c;在这里会记录下正点原子Linux ARM MX6ULL 开发板根据配套的哔哩哔哩学习视频所作的实验和笔记内容。本文大量的引用了正点原子哔哔哩网…

[论文笔记] EcomGPT:COT扩充数据的电商大模型

社区供稿 | EcomGPT:基于任务链数据的电商大模型(附魔搭推理实践) - 知乎 https://arxiv.org/pdf/2312.15696.pdf EcomInstruct指令数据集构建 数据集组成 COT方式构造垂域训练数据:把原本的垂域任务分解成了原子任务,构造了基于解决原子任务的数据。这样能用类似…

网页模版如何用

现在的网页模版已经得到了许多人的喜爱和使用。随着人们对互联网的需求不断增加&#xff0c;更多的公司和组织需要拥有自己的网站&#xff0c;以推广他们的品牌和服务。而网页模版为他们提供了一个简单而高效的方法来创建自己的网站。 网页模版是预先设计好的网站模板&#xff…