java虚拟机内存管理
文章目录
- 概要
- 一、jdk7与jdk8内存结构的差异
- 二、程序计数器
- 三、虚拟机栈
- 3.1 什么是虚拟机栈
- 3.2 什么是栈帧
- 3.3 栈帧的组成
- 四、本地方法栈
- 五、堆
- 5.1 堆的特点
- 5.2 堆的结构
- 5.3 堆的参数配置
- 六、方法区
- 6.1 方法区结构
- 6.2 运行时常量池
- 七、元空间
概要
根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。
其中各个部分的概述如下:
名称 | 特征 | 作用 | 配置参数 | 异常 |
---|---|---|---|---|
程序计数器 | 线程私有,生命周期与线程相同 | 字节码行号指示器 | 无 | 无 |
虚拟机栈 | 线程私有,生命周期与线程相同,使用连续的内存空间 | 存储信息如上图 | -Xss | StackOverflowError/ OutOfMemoryError |
堆 | 线程共享,生命周期与虚拟机相同,可以不使用连续的内存地址 | 保存对象实例,所有对象实例(包括数组)都要在堆上分配 | -Xms -Xsx -Xmn | OutOfMemoryError |
方法区 | 线程共享,生命周期与虚拟机相同, 可以不使用连续的内存地址 | 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 | -XX:PermSize:16M -XX:MaxPermSize64M -XX:MetaspaceSize=16M -XX:MaxMetaspaceSize=64M | OutOfMemoryError |
本地方法栈 | 线程私有 | 为虚拟机使用到的Native 方法服务 | 无 | StackOverflowError/ OutOfMemoryError |
JVM分为五大模块: 类装载器子系统 、 运行时数据区 、 执行引擎 、 本地方法接口 和 垃圾收集模块 。
一、jdk7与jdk8内存结构的差异
Java7和Java8内存结构的不同主要体现在方法区的实现。
方法区是java虚拟机规范中定义的一种概念上的区域,不同的厂商可以对虚拟机进行不同的实现。
我们通常使用的Java SE都是由Sun JDK和OpenJDK所提供,这也是应用最广泛的版本。而该版本使用的VM就是HotSpot VM。通常情况下,我们所讲的java虚拟机指的就是HotSpot的版本。
JDK7的内存结构
永久代是 hotspot 在1.7及之前才有的设计,1.8+,以及其他虚拟机并不存。可以说,永久代是1.7的 hotspot 偷懒的结果,他在堆里划分了一块来实现方法区的功能,叫永久代。
因为这样可以借助堆的垃圾回收来管理方法区的内存,而不用单独为方法区再去编写内存管理程序。
同时代的其他虚拟机,如 J9 , Jrockit 等,没有这个概念。后来 hotspot认识到,永久代来做这件事不是一个好主意。1.7已经从永久代拿走了一部分数据(静态变量和运行时常量池转移到了堆中),直到1.8+彻底去掉了永久代,方法区大部分迁移到了 metaspace
(注意不是全部,不是全部)
JDK8的内存结构
从jdk1.8开始已经将方法区中实现的永久代去掉了,并用元空间( class metadata space
)代替了之前的永久代,元空间的存储位置是:本地内存/直接内存,并且将方法区大部分迁移到了元空间。
方法区Java8之后的变化小结:
- 移除了永久代(
PermGen
),替换为元空间(Metaspace
) - 永久代中的
class metadata
(类元信息)转移到了native memory(本地内存,而不是虚拟机) - 永久代中的
interned Strings
(字符串常量池) 和class static variables
(类静态变量)转移到了Java heap
- 永久代参数(
PermSize MaxPermSize
)-> 元空间参数(MetaspaceSize MaxMetaspaceSize
)
Java8 为什么使用元空间替代永久代,这样做有什么好处呢?
官方给出的解释是:
- 移除永久代是为了融合 HotSpot JVM 与 JRockit VM 而做出的努力,因为 JRockit 没有永久代,所以不需要配置永久代。
- 永久代内存经常不够用或发生内存溢出,抛出异常
java.lang.OutOfMemoryError: PermGen
。这是因为在 JDK1.7 版本中,指定的PermGen
区大小为8M,由于PermGen
中类的元数据信息在每次FullGC
的时候都可能被收集,但回收率都偏低,成绩很难令人满意; - 为
PermGen
分配多大的空间很难确定,PermSize
的大小依赖于很多因素,比如,JVM 加载的 class 总数、常量池的大小和方法的大小等,而jdk1.8以后的元空间大小就只受本机总内存的限制(如果不设置参数的话),因为它使用的是本地内存。
二、程序计数器
程序计数器(Program Counter Register
):也叫PC寄存器,是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令、分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
PC寄存器的特点
(1)区别于计算机硬件的pc寄存器,两者不略有不同。计算机用pc寄存器来存放“伪指令”或地址,而相对于虚拟机,pc寄存器它表现为一块内存,虚拟机的pc寄存器的功能也是存放伪指令,更确切的说存放的是将要执行指令的地址。
(2)当虚拟机正在执行的方法是一个本地(native
)方法的时候,jvm的pc寄存器存储的值是undefined
。
(3)程序计数器是线程私有的,它的生命周期与线程相同,每个线程都有一个。
(4)此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError
情况的区域。
Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处
理器只会执行一条线程中的指令。
因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数
器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
三、虚拟机栈
3.1 什么是虚拟机栈
Java虚拟机栈(Java Virtual Machine Stacks
)也是线程私有的,即生命周期和线程相同。Java虚拟机栈和线程同时创建,用于存储栈帧。每个方法在执行时都会创建一个栈帧(Stack Frame
),用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直到执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
public class StackDemo {public static void main(String[] args) {StackDemo sd = new StackDemo();sd.A();}public void A() {int a = 10;System.out.println(" method A start");System.out.println(a);B();System.out.println("method A end");}public void B() {int b = 20;System.out.println(" method B start");C();System.out.println("method B end");}private void C() {int c = 30;System.out.println(" method C start");System.out.println("method C end");}
}
3.2 什么是栈帧
栈帧(Stack Frame)
是用于支持虚拟机进行方法调用和方法执行的数据结构。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法从调用至执行完成的过程,都对应着一个栈帧在虚拟机栈里从入栈到出栈的过程。
3.3 栈帧的组成
栈帧大体都包含四个区域:局部变量表、操作数栈、动态连接、 返回地址
局部变量表
部变量表(Local Variable Table
)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。
包括8种基本数据类型、对象引用(reference
类型)和returnAddress
类型(指向一条字节码指令的地址)。其中64位长度的long
和double
类型的数据会占用2个局部变量空间(Slot
),其余的数据类型只占用1个。
操作数栈
操作数栈(Operand Stack
)也称作操作栈,是一个后入先出栈(LIFO)。随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。
操作数栈作用小结:
- 主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间
- 操作数栈就是JVM执行引擎的一个工作区, Java虚拟机的解释执行引擎被称为"基于栈的执行引擎",其中所指的栈就是指-操作数栈
- 为了实现java的跨平台,选择了面向操作数栈的指令集架构而没有选择直接基于CPU寄存器的指令集架构(由执行引擎面向更底层),基于栈的指令集主要的优点就是可移植,寄存器由硬件直接提供,程序直接依赖这些硬件寄存器则不可避免地要受到硬件的约束,但是栈架构指令集的主要缺点是执行速度相对来说会稍慢一些,因为栈实现在内存之中,频繁的栈访问也就意味着频繁的内存访问,相对于CPU来说,内存始终是执行速度的瓶颈;
动态链接
Java虚拟机栈中,每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用,持有这个引用的目的是为了支持方法调用过程中的动态链接(Dynamic Linking
)。
动态链接的作用是将符号引用转换成直接引用
返回地址
方法返回地址存放调用该方法的PC寄存器的值。一个方法的结束,有两种方式:正常地执行完成,出现未处理的异常非正常的退出。无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的PC计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息。
无论方法是否正常完成,都需要返回到方法被调用的位置,程序才能继续进行。
四、本地方法栈
本地方法栈(Native Method Stacks
) 与虚拟机栈所发挥的作用是非常相似的, 其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码) 服务, 而本地方法栈则是为虚拟机使用到的本地(Native
) 方法服务。
特点:
- 本地方法栈加载
native
方法 - 是线程私有,生命周期跟线程相同,每个线程都有一个
- 跟java虚拟虚拟机栈一样,规定了两种类型异常:
a)StackOverFlowError
:线程请求的栈深度大于所允许的深度。
b)OutOfMemoryError
:本地方法栈扩展时无法申请到足够的内存
五、堆
对于Java应用程序来说, Java堆(Java Heap)
是虚拟机所管理的内存中最大的一块。 Java堆是被所 有线程共享的一块内存区域, 在虚拟机启动时创建。 此内存区域的唯一目的就是存放对象实例, Java 世界里“几乎”所有的对象实例都在这里分配内存。
5.1 堆的特点
- Java虚拟机所管理的内存中最大的一块
- jvm所有线程共享(堆中也包含私有的线程缓冲区
Thread Local Allocation Buffer (TLAB)
) - 在虚拟机启动时创建
- 几乎所有的对象实例以及数组都在这里分配内存
- java堆时垃圾收集器管理的主要区域
- 从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以Java堆还可以细分为:新生代和老年代;新生代又可以分为:
Eden
空间、From Survivor
空间、To Survivor
空间。 - 堆是计算机物理存储上不连续的、逻辑上是连续的,也是大小可调节的(通过
-Xms
和-Xmx
控制)。 - 方法结束后,堆中对象不会马上移出仅仅在垃圾回收的时候时候才移除
- 如果在堆中没有内存完成实例的分配,并且堆也无法再扩展时,将会抛出
OutOfMemoryError
异常
5.2 堆的结构
现在垃圾回收器都使用分代理论,堆空间也分类如下:
在Java7 Hotspot虚拟机中将Java堆内存分为3个部分:
- 青年代
Young Generation
- 老年代
Old Generation
- 永久代
Permanent Generation
在Java8以后,由于方法区的内存不在分配在Java堆上,而是存储于本地内存元空间Metaspace
中,所以永久代就不存在了
5.3 堆的参数配置
参考:参数配置
JVM中存储java对象可以被分为两类:
- 年轻代(
Young Gen
):年轻代主要存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。年轻代分成1个Eden Space
和2个Suvivor Space
(from
和to
)。 - 年老代(
Tenured Gen
):年老代主要存放JVM认为生命周期比较长的对象(经过几次的Young Gen
的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁.
-XX:NewRatio=ratio
Sets the ratio between young and old generation sizes. By default, this option is set to 2. The following example shows how to set the young/old ratio to 1:
-XX:NewRatio=1
-XX:NewRatio=2
:默认值,标识新生代占1,老年代占2,新生代占整个堆的1/3;
修改占比 -XX:NewPatio=4
, 标识新生代占1 , 老年代占4 , 新生代占整个堆的1/5
XX:SurvivorRatio=ratio
Sets the ratio between eden space size and survivor space size. By default, this option is set to 8. The following example shows how to set the eden/survivor space ratio to 4:
-XX:SurvivorRatio=4
Eden
空间和另外两个Survivor
空间占比分别为8:1:1
可以通过操作选项 -XX:SurvivorRatio
调整这个空间比例。 比如 -XX:SurvivorRatio=8
堆的总大小可由-Xms
跟-Xmx
来配置
JVM 每次只会使用 Eden
和其中的一块 Survivor
区域来为对象服务,所以无论什么时候,总是有一块 Survivor
区域是空闲着的。因此,新生代实际可用的内存空间为 9/10
( 即90% )的新生代空间。
六、方法区
方法区(Method Area
) 与Java堆一样, 是各个线程共享的内存区域, 它用于存储已被虚拟机加载的类型信息、常量、 静态变量、 即时编译器编译后的代码缓存等数据。
官方文档:方法区
方法区中存储的信息大致可分以下两类:
- 类信息:主要指类相关的版本、字段、方法、接口描述、引用等
- 运行时常量池:编译阶段生成的常量与符号引用、运行时加入的动态变量
方法区在虚拟机规范里这是一个逻辑概念,元空间、永久代是方法区具体的落地实现。
在jdk1.6里,用永久代来实现方法区,物理空间上用的时堆的内存(目的是利用堆的垃圾回收来管理方
法区的内存)。字符串常量是运行时常量池的一部分,也就是归属于方法区,放在了永久代里。这个时候经常会出现的一个错误就是:java.lang.OutOfMemoryError: PermGen space
。
jdk1.7已经从永久代拿了一部分数据(静态变量和运行时常量池)转移到了堆中
6.1 方法区结构
类加载器将Class文件加载到内存之后,将类的信息存储到方法区中
方法区中存储的内容:
- 类型信息(域信息、方法信息)
- 运行时常量池
类型信息
对每个加载的类型(类Class
、接口 interface
、枚举enum
、注解 annotation
),JVM必须在方法区中存储以下类型信息:
- 这个类型的完整有效名称(全名 = 包名.类名)
- 这个类型直接父类的完整有效名(对于
interface
或是java.lang.Object
,都没有父类) - 这个类型的修饰符(
public
,abstract
,final
的某个子集) - 这个类型直接接口的一个有序列表
域信息
域信息,即为类的属性,成员变量
JVM必须在方法区中保存类所有的成员变量相关信息及声明顺序。
域的相关信息包括:域名称、域类型、域修饰符(pυblic
、private
、protected
、static
、final
、volatile
、transient
的某个子集)
方法信息
JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:
- 方法名称方法的返回类型(或
void
) - 方法参数的数量和类型(按顺序)
- 方法的修饰符
public
、private
、protected
、static
、final
、synchronized
、native
、abstract
的一个子集 - 方法的字节码bytecodes、操作数栈、局部变量表及大小(
abstract
和native
方法除外) - 异常表(
abstract
和native
方法除外)。每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏
移地址、被捕获的异常类的常量池索引
6.2 运行时常量池
在jvm规范中,方法区除了存储类信息之外,还包含了运行时常量池。这里
首先要来讲一下常量池的分类:
- Class常量池(静态常量池)
- 运行时常量池
- 字符串常量池(没有明确的官方定义,其目的是为了更好地使用
String
)
常量池经常会被搞混,要准确地理解,首先来看基本定义
静态常量池:存放编译期间生成的各种字面量与符号引用
运行时常量池:常量池表在运行时的表现形式
编译后的字节码文件中包含了类型信息、域信息、方法信息等。通过ClassLoader
将字节码文件的常量池(静态常量池)中的信息加载到内存中,存储在了方法区的运行时常量池中。
什么叫字面量与符号引用呢?
静态常量池
.class
文件中除了有类的版本、字段、方法和接口等描述信息外,还有一项信息是常量池 ( Constant Pool Table
),用于存放编译期间生成的各种字面量和符号引用,之所以说它是静态的常量池是因为这些都只是躺在 .class
文件中的静态数据,此时还没被加载到内存.
/*** 1. 使用jdk1.8编译* 2. 使用 javap -v ClassConstantPool.class*/
public class ClassConstantPool {private static String a = "abc";private String f = "def";private static int b = 123;private final int c = 456;private int d = 789;private float e;Gucci gucci = new Gucci();class Gucci {}
}
反编译后,截取部分信息如下:
字面量:给基本类型变量的赋值就叫做字面量或字面值,字面量是编译后生成的产物。
比如:String a = "b"
,这里的“b”就是字符串字面量,同样类推还有整数字面量,浮点类型字面量,字符字面量
符号引用:符号引用以一组符号来描述所引用的目标。符号引用可以是任何形式的字面量,JAVA 在编译的时候一个每个 java 类都会被编译成一个 class 文件,但在编译的时候虚拟机并不知道所引用类的地址(实际地址),就用符号引用来代替,而在类的解析阶段(类加载的一个过程)就是为了把这个符号引用转化成为真正的地址。
比如:ClassConstantPool
类被编译成一个class
文件时,发现引用了Gucci
类,,但是在编译时并不知道Gucci
类的实际内存地址,因此只能使用符号引用(com/ocean/constance/ClassConstantPool$Gucci
)来代替。而在类装载器装
载Guuci
类时,此时可以通过虚拟机获取Guuci
类 的实际内存地址,因此便可以将符号com/ocean/constance/ClassConstantPool$Gucci
替换为Guuci
类的实际内存地址。
运行时常量池
运行时常量池( Runtime Constant Pool
)是每一个类或接口的常量池( Constant_Pool
)的运行时表示形式,它包括了若干种不同的常量:从编译期可知的数值字面量到必须运行期解析后才能获得的方法或字段引用。
运行时常量池是在类加载完成之后,将 静态常量池中的符号引用值转存到运行时常量池中,类在解析之后,将符号引用替换成直接引用。 另外运行时常量池的物理存储位置要注意两点:
- 运行时常量池在 JDK1.7 版本之后,就移到堆内存中了,这里指的是物理空间,而逻辑上还是属于方法区(方法区是逻辑分区)。
- 在 JDK1.8 中,使用元空间代替永久代来实现方法区,但是方法区从定义上并没有改变,所谓 “Your father will always be your father” 。变动的只是方法区中内容的物理存放位置,运行时常量池和字符串常量池被移动到了堆中而并没有在元空间。但是不论它们物理上如何存放,逻辑上还是属于方法区的。
字符串常量池
字符串常量池这个概念是有争议的,很多正式的虚拟机规范文档,都没有对这个概念作一个明确的官方定义。
以 JDK1.8 为例,字符串常量池是存放在堆中,并且与 java.lang.String
类有很大关系。设计这块内存区域的原因在于: String
对象作为 Java 语言中重要的数据类型,是内存中占据空间最大的一个对象。高效地使用字符串,可以提升系统的整体性能。
七、元空间
在JDK1.7之前,HotSpot 虚拟机用永久代来实现方法区。而从 JDK 1.8 开始,移除永久代,用元空间来实现方法区,它位于本地内存中,而不是虚拟机内存中。
永久代跟元空间对比如下:
- 存储位置不同:永久代在物理上是堆的一部分,和新生代、老年代的地址是连续的,而元空间属于本地内存。
- 存储内容不同:在原来的永久代划分中,永久代用来存放类的元数据信息、静态变量以及常量池等。现在类的元信
息存储在元空间中,静态变量和常量池等并入堆中,相当于原来的永久代中的数据,被元空间和堆内存给瓜分了。
Metaspace相关参数:
XX:MetaspaceSize
·,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如
果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize
时,适当提高该值。-XX:MaxMetaspaceSize
,最大空间,默认是没有限制的。如果没有使用该参数来设置类的元数据的大小,其最大可利用空间是整个系统内存的可用空间。JVM也可以增加本地内存空间来满足类元数据信息的存储。但是如果没有设置最大值,则可能存在bug导致Metaspace的空间在不停的扩展,会导致机器的内存不足;进而可能出现swap内存被耗尽;最终导致进程直接被系统直接kill掉。如果设置了该参数,当Metaspace剩余空间不足,会抛出:java.lang.OutOfMemoryError: Metaspace space
-XX:MinMetaspaceFreeRatio
,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
-XX:MaxMetaspaceFreeRatio
,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集
相关文章:
java虚拟机内存管理
文章目录 概要一、jdk7与jdk8内存结构的差异二、程序计数器三、虚拟机栈3.1 什么是虚拟机栈3.2 什么是栈帧3.3 栈帧的组成 四、本地方法栈五、堆5.1 堆的特点5.2 堆的结构5.3 堆的参数配置 六、方法区6.1 方法区结构6.2 运行时常量池 七、元空间 概要 根据 JVM 规范࿰…...
Hive实战:词频统计
文章目录 一、实战概述二、提出任务三、完成任务(一)准备数据文件1、在虚拟机上创建文本文件2、将文本文件上传到HDFS指定目录 (二)实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、基于HDFS文件创建外部表4、查询单词表&a…...
FairyGUI-Cocos Creator官方Demo源码解读
博主在学习Cocos Creator的时候,发现了一款免费的UI编辑器FairyGUI。这款编辑器的能力十分强大,但是网上的学习资源比较少,坑比较多,主要学习方式就是阅读官方文档和练习官方Demo。这里博主进行官方Demo的解读。 从gitee上克隆项目…...
LabVIEW利用视觉引导机开发器人精准抓取
LabVIEW利用视觉引导机开发器人精准抓取 本项目利用单目视觉技术指导多关节机器人精确抓取三维物体的技术。通过改进传统的相机标定方法,结合LabVIEW平台的Vision Development和Vision Builder forAutomated Inspection组件,优化了摄像系统的标定过程&a…...
【Linux】指令(本人使用比较少的)——笔记(持续更新)
文章目录 ps -axj:查看进程ps -aL:查看线程echo $?:查看最近程序的退出码jobs:查看后台运行的线程组fd 任务号:将后台任务提到前台bg 任务号:将暂停的后台程序重启netstat -nltp:查看服务及监听…...
032 - STM32学习笔记 - TIM基本定时器(一) - 定时器基本知识
032 - STM32学习笔记 - TIM定时器(一) - 基本定时器知识 这节开始学习一下TIM定时器功能,从字面意思上理解,定时器的基本功能就是用来定时,与定时器相结合,可以实现一些周期性的数据发送、采集等功能&#…...
轮廓检测与处理
轮廓检测 先将图像转换成二值 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图 ret, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 变为二值,大于127置为255,小于100置为0.使用cv2.findContours(thresh, cv2.RETR_TREE, cv2.…...
跟着LearnOpenGL学习11--材质
文章目录 一、材质二、设置材质三、光的属性四、不同的光源颜色 一、材质 在现实世界里,每个物体会对光产生不同的反应。 比如,钢制物体看起来通常会比陶土花瓶更闪闪发光,一个木头箱子也不会与一个钢制箱子反射同样程度的光。 有些物体反…...
Java guava partition方法拆分集合自定义集合拆分方法
日常开发中,经常遇到拆分集合处理的场景,现在记录2中拆分集合的方法。 1. 使用Guava包提供的集合操作工具栏 Lists.partition()方法拆分 首先,引入maven依赖 <dependency><groupId>com.google.guava</groupId><artifa…...
GLTF编辑器-位移贴图实现破碎的路面
在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 位移贴图是一种可以用于增加模型细节和形状的贴图。它能够在渲染时针…...
多维时序 | MATLAB实现SSA-BiLSTM麻雀算法优化双向长短期记忆神经网络多变量时间序列预测
多维时序 | MATLAB实现SSA-BiLSTM麻雀算法优化双向长短期记忆神经网络多变量时间序列预测 目录 多维时序 | MATLAB实现SSA-BiLSTM麻雀算法优化双向长短期记忆神经网络多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现SSA-BiLSTM麻雀算法优化…...
docker安装Nacos和Rabbitmq
一、安装Nacos 首先需要拉取对应的镜像文件:(切换版本加上对应版本号即可,默认最新版) docker pull nacos/nacos-server 接着挂载目录: mkdir -p /mydata/nacos/logs/ #新建logs目录 mkdir -p …...
Android MVC 写法
前言 Model:负责数据逻辑 View:负责视图逻辑 Controller:负责业务逻辑 持有关系: 1、View 持有 Controller 2、Controller 持有 Model 3、Model 持有 View 辅助工具:ViewBinding 执行流程:View >…...
网络层解读
基本介绍 概述 当两台主机之间的距离较远(如相隔几十或几百公里,甚至几千公里)时,就需要另一种结构的网络,即广域网。广域网尚无严格的定义。通常是指覆盖范围很广(远超过一个城市的范围)的长距离的单个网络。它由一些结点交换机以及连接这些…...
js for和forEach 跳出循环 替代方案
1 for循环跳出 for(let i0;i<10;i){if(i5){break;}console.log(i) }在函数中也可以return跳出循环 function fn(){for(let i0;i<10;i){if(i5){return;}console.log(i)} } fn()for ... of效果同上 2 forEach循环跳出 break会报错 [1,2,3,4,5,6,7,8,9,10].forEach(i>…...
如何使用ArcGIS Pro自动矢量化建筑
相信你在使用ArcGIS Pro的时候已经发现了一个问题,那就是ArcGIS Pro没有ArcScan,在ArcGIS Pro中,Esri确实已经移除了ArcScan,没有了ArcScan我们如何自动矢量化地图,从地图中提取建筑等要素呢,这里为大家介绍…...
交互式笔记Jupyter Notebook本地部署并实现公网远程访问内网服务器
最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 文章目录 1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下…...
41.坑王驾到第七期:uniapp开发微信小程序引用组件时报错!
一、错误再现 页面login引用了一个组件register,运行至小程序开发工具报错。 xxx.js 已被代码依赖分析忽略,无法被其他模块引用。 二、解决办法 在微信小程序的配置文件中找到setting节点,增加两个配置项。 “ignoreDevUnusedFiles”: fa…...
挂载与解挂载
一. 挂载 1.什么是挂载 将系统中的文件夹和磁盘做上关联,使用文件夹等于使用磁盘 2.mount 2.1 格式 mount [ -t 类型 ] 存储设备 挂载点目录 mount -o loop ISO镜像文件 挂载点目录 注意:指明要挂载的设备 设备文件:例如:/dev/sda5 卷…...
UGUI Panel的显示和隐藏优化
unity UI如何开启(显示)或者关闭(隐藏)Panel界面,相信大家都是知道的,但是如何做最好呢? 可能大家一般开启/关闭界面的方法就是直接SetActive吧。这样做通常是可以的,简答快速地解决…...
Linux:多文件编辑
多文件编辑 1.使用vim编辑多个文件 编辑多个文件有两种形式,一种是在进入vim前使用的参数就是多个文件。另一种就是进入vim后再编辑其他的文件。 同时创建两个新文件并编辑 $ vim 1.txt 2.txt默认进入1.txt文件的编辑界面 命令行模式下输入:n编辑2.txt文件&…...
模式识别与机器学习-概率图模型
模式识别与机器学习-概率图模型 概率图模型三大基本问题表示推断学习 有向概率图模型例子三种经典的图 HMMViterbi 算法 谨以此博客作为复习期间的记录 概率图模型三大基本问题 概率图模型通常涉及三个基本问题,即表示(Representation)、推…...
RK3566 ANDROID 11 平台上适配移远EC200A
适配前理清楚一下调试的流程: 1.该模块为LGA封装,需要控制上电时序模块才能正常上电工作: 2.模块供电正常后,读取模组的PID 和VID 并将其ID添加到内核里面,确保USB转Serial端口能够正常生成: 3.生成ttyUSB0~ttyUSB2端口后,确保rild进程正常启动,能够正常加载ril库; …...
存算分离降本增效,StarRocks 助力聚水潭 SaaS 业务服务化升级
作者:聚水潭数据研发负责人 溪竹 聚水潭是中国领先的 SaaS 软件服务商,核心产品是电商 ERP,协同350余家电商平台,为商家提供综合的信息化、数字化解决方案。公司是偏线下商家侧的 toB 服务商,员工人数超过3500…...
Linux 内核学习笔记: hlist 的理解
前言 最近阅读 Linux 内核时,遇到了 hlist,这个 hlist 用起来像是普通的链表,但是为何使用 hlist,hlist 是怎么工作的? 相关代码 hlist_add_head(&clk->clks_node, &core->clks); /*** clk_core_link_…...
几种设计模式介绍
前言 设计模式是一种用于解决软件开发中常见问题的通用解决方案,它可以提高代码的可读性、可维护性和可复用性。前端开发中也有很多应用设计模式的场景,比如处理异步操作、优化性能、封装复杂逻辑等。 前端开发中常见的设计模式有以下几种: …...
拓展操作(三) jenkins迁移到另一个机器
让清单成为一种习惯 互联网时代的变革,不再是简单的开发部署上线,持续,正确,安全地把事情做好尤其重要;把事情做好的前提是做一个可量化可执行的清单,让工程师就可以操作的清单而不是专家才能操作: 设定检查点 根据节点执行检查程序操作确认或边读边做 二者选其一不要太…...
重定向和转发的区别
重定向 1、定义 用户通过浏览器发送一个请求,Tomcat服务器接收这个请求,会给浏览器发送一个状态码302,并设置一个重定向的路径,浏览器如果接收到了这个302的状态码以后,就会去自动加载服务器设置的路径 一个页面跳转…...
基于ElementUI二次封装弹窗组件
效果: 一、自定义内容类型弹窗 <!-- title:对话框的标题confirmLoading:当前是否处于提交中titleCenter:对话框标题居中方式footerCenter:底部按钮的对其方式visible:是否显示弹窗width:设置…...
linux cat命令改变功能显示当前文件行号
linux的cat命令使用-n显示多个文件行号时,行号是累加的,不是到了新文件就重新计数。这样满足不了我的需求。如果到了新文件能够重新计数,就能使用-nf(在上一篇-f显示文件名功能的基础上)加| grep xxx,既能直…...
广东万高建设网站/哪家建设公司网站
您将在本节继续团队介绍页面的制作,为另一个团队成员制作动画展示效果。首先使用键盘上的快捷键,复制当前幻灯片。 选择此处的椭圆图片。 在视图比例滑杆上点击,缩小幻灯片的显示比例。 按下键盘上的shift键。 在按下该键的同时,点击此处以同时选择多个对象。 向左侧拖…...
化工厂网站建设/免费个人自助建站
基本模式匹配一切从最基本的开始。模式,是正规表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂,往往用特殊的字符表示一个范围内的字符、重复出现,…...
网站可以做话筒台标吗/网络广告联盟
在上一篇《用于修改配置的存储过程 | 全方位认识 sys 系统库》中,我们介绍了sys 系统库中用于修改配置的存储过程,利用这些存储过程可以代替修改performance_schema配置表的DML语句等操作,本期的内容讲介绍用于查看performance_schema配置信息…...
做做做做网站/app推广员怎么做
在统计应用推广或ASO效果时,我们通常会碰到很多数据指标,而这些数据指标的实际数值不仅可以显示出应用的性能好坏,还能帮我们找出运营过程中的不足。 接下来,就和大家分享一些非常重要的数据指标,希望能帮大家及时把控…...
wordpress安装主题报错/最佳的搜索引擎
一种基于ipmi的对服务器进行自动化重启测试的方法【技术领域】[0001]本发明涉及重启测试技术技术,尤其涉及一种基于IPMI的对服务器进行自动化重启测试的方法。【背景技术】[0002]随着服务器行业的高速发展,在各个领域中越来越多的客户采用计算能力更强的…...
网站建设评审/免费的网站域名查询565wcc
在贴代码之前,首先需要给QQ邮箱开服务IMAP/SMTP服务,详细开通方法见 "开通方法"(可能需要发送收费短信,所以只要开通这一个服务就好了)。 这边主要就是为了一个服务的授权码,如下图: 服务开好之后࿰…...