Java知识复习(五)JVM虚拟机

news2024/11/24 16:23:49

1、虚拟机的自动内存管理和C/C++的区别

C/C++开发程序时需要为每一个new操作去写对应的delete/free操作,不容易出现内存泄漏和溢出问题。而Java程序将内存控制权交给了Java虚拟机

2、JVM的运行机制

1、Java程序的具体运行过程如下:

  1. Java源文件被编译器编译成字节码文件
  2. JVM将字节码文件编译成相应操作系统的机器码
  3. 机器码调用相应操作系统的本地方法库执行相应的方法

2、虚拟机结构

Java虚拟机包括类加载器子系统、运行时数据区、执行引擎、本地接口库等
在这里插入图片描述

3、JVM的内存区域

1、内存区域划分: 线程私有区域、线程共享区域和直接内存
在这里插入图片描述

  • 线程私有区域的生命周期与线程相同
  • 线程共享区域的生命周期与虚拟机相同
  • 直接内存也叫堆外内存,它不是JVM运行时数据区的一部分,但在并发编程中被频繁调用

2、程序计数器: 线程私有,无内存溢出问题

  • 每个运行中的线程都有一个独立的程序计数器,在方法正在执行时,该方法的程序计数器记录的是实时虚拟机字节码指令的地址;如果该方法执行的是Native方法,则程序计数器的值为空
  • 程序计数器属于“线程私有”的内存区域,它是唯一没有Out Of Memory(内存溢出)的区域

3、虚拟机栈: 线程私有,描述Java方法的执行过程

  • 虚拟机栈是描述Java方法的执行过程的内存模型,它在当前栈帧中存储了局部变量表、操作数栈、动态链接、方法出口等信息。
  • 栈帧用来记录方法的执行过程,在方法被执行时虚拟机会为其创建一个与之对应的栈帧,方法的执行和返回对应栈帧在虚拟机栈中的入栈和出栈
    在这里插入图片描述

4、本地方法区: 线程私有

  • 本地方法区和虚拟机栈的作用类似,区别是虚拟机栈为执行Java方法服务,本地方法栈为Native方法服务

5、堆: 也叫作运行时内存,线程共享

  • 在JVM运行过程中创建的对象和产生的数据都被存储在堆中,堆是被线程共享的内存区域,也是垃圾收集器进行垃圾回收的最主要的内存区域
  • 由于现代JVM采用分代收集算法,因此Java堆从GC(Garbage Collection,垃圾回收)的角度还可以细分为:新生代、老年代和永久代

6、方法区: 线程共享

  • 方法区也被称为永久代,用于存储常量、静态变量、类信息、即时编译器编译后的机器码、运行时常量池等数据
  • 永久代的内存回收主要针对常量池的回收和类的卸载,因此可回收的对象很少
  • 在即时编译后,代码的内容将在执行阶段(类加载完成后)被保存在方法区的运行时常量池中
    在这里插入图片描述

4、JVM的运行时内存

1、JVM的运行时内存也叫作JVM堆:可分类为如下图所示在这里插入图片描述
2、新生代: Eden区、ServivorTo区和ServivorFrom区

  • JVM新创建的对象(除了大对象外)会被存放在新生代,默认占1/3堆内存空间。由于JVM会频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收
  • Eden区:Java新创建的对象首先会被存放在Eden区,如果新创建的对象属于大对象,则直接将其分配到老年代
  • ServivorTo区:保留上一次MinorGC时的幸存者
  • ServivorFrom区:将上一次MinorGC时的幸存者作为这一次MinorGC的被扫描者
  • 新生代的GC过程叫作MinorGC,采用复制算法实现

3、老年代

  • 老年代主要存放有长生命周期的对象和大对象。老年代的GC过程叫作MajorGC,采用标记清除算法
  • 在老年代,对象比较稳定,MajorGC不会被频繁触发。在进行MajorGC前,JVM会进行一次MinorGC,在MinorGC过后仍然出现老年代空间不足或无法找到足够大的连续空间分配给新创建的大对象时,会触发MajorGC进行垃圾回收,释放JVM的内存空间

4、永久代

  • 永久代指内存的永久保存区域,主要存放Class和Meta(元数据)的信息。
  • Class在类加载时被放入永久代。永久代和老年代、新生代不同,GC不会在程序运行期间对永久代的内存进行清理,这也导致了永久代的内存会随着加载的Class文件的增加而增加,在加载的Class文件过多时会抛出Out Of Memory异常
  • 需要注意的是,在Java 8中永久代已经被元数据区(也叫作元空间)取代。元数据区的作用和永久代类似,二者最大的区别在于:元数据区并没有使用虚拟机的内存,而是直接使用操作系统的本地内存。因此,元空间的大小不受JVM内存的限制,只和操作系统的内存有关。

5、确定垃圾

1、如何确定垃圾: Java采用引用计数法和可达性分析来确定对象是否应该被回收在这里插入图片描述
2、引用计数法

  • 在Java中如果要操作对象,就必须先获取该对象的引用,因此可以通过引用计数法来判断一个对象是否可以被回收。在为对象添加一个引用时,引用计数加1;在为对象删除一个引用时,引进计数减1;如果一个对象的引用计数为0,则表示此刻该对象没有被引用,可以被回收
  • 引用计数法容易产生循环引用问题。循环引用指两个对象相互引用,导致它们的引用一直存在,而不能被回收

3、可达性分析

  • 具体做法是首先定义一些GC Roots对象,然后以这些GC Roots对象作为起点向下搜索,如果在GC roots和一个对象之间没有可达路径,则称该对象是不可达的
  • 不可达对象要经过至少两次标记才能判定其是否可以被回收,如果在两次标记后该对象仍然是不可达的,则将被垃圾收集器回收。

6、垃圾回收算法

  • 4种算法:标记清除、复制、标记整理、分代收集
    在这里插入图片描述

1、标记清除算法

  • 标记清除算法是基础的垃圾回收算法,其过程分为标记和清除两个阶段。在标记阶段标记所有需要回收的对象,在清除阶段清除可回收的对象并释放其所占用的内存空间
  • 由于标记清除算法在清理对象所占用的内存空间后并没有重新整理可用的内存空间,因此如果内存中可被回收的小对象居多,则会引起内存碎片化的问题,继而引起大对象无法获得连续可用空间的问题在这里插入图片描述

2、复制算法

  • 复制算法是为了解决标记清除算法内存碎片化的问题而设计的。
  • 复制算法首先将内存划分为两块大小相等的内存区域,即区域1和区域2,新生成的对象都被存放在区域1中,在区域1内的对象存储满后会对区域1进行一次标记,并将标记后仍然存活的对象全部复制到区域2中,这时区域1将不存在任何存活的对象,直接清理整个区域1的内存即可
  • 复制算法的内存清理效率高且易于实现,但由于同一时刻只有一个内存区域可用,即可用的内存空间被压缩到原来的一半,因此存在大量的内存浪费
    在这里插入图片描述

3、标记整理算法

  • 标记整理算法结合了标记清除算法和复制算法的优点,其标记阶段和标记清除算法的标记阶段相同,在标记完成后将存活的对象移到内存的另一端,然后清除该端的对象并释放内存
    在这里插入图片描述

4、分代收集算法

  • 无论是标记清除算法、复制算法还是标记整理算法,都无法对所有类型(长生命周期、短生命周期、大对象、小对象)的对象都进行垃圾回收。因此,针对不同的对象类型,JVM采用了不同的垃圾回收算法,该算法被称为分代收集算法
  • 分代收集算法根据对象的不同类型将内存划分为不同的区域,JVM将堆划分为新生代和老年代。新生代主要存放新生成的对象,其特点是对象数量多但是生命周期短,在每次进行垃圾回收时都有大量的对象被回收;老年代主要存放大对象和生命周期长的对象,因此可回收的对象相对较少。因此,JVM根据不同的区域对象的特点选择了不同的算法
  • 大部分JVM在新生代都采用了复制算法,JVM将新生代进一步划分为一块较大的Eden区和两块较小的Servivor区,Servivor区又分为ServivorFrom区和ServivorTo区。JVM在运行过程中主要使用Eden区和ServivorFrom区,进行垃圾回收时会将在Eden区和ServivorFrom区中存活的对象复制到ServivorTo区,然后清理Eden区和ServivorFrom区的内存空间
  • 老年代主要存放生命周期较长的对象和大对象,因而每次只有少量非存活的对象被回收,因而在老年代采用标记清除算法
  • 在JVM中还有一个区域,即方法区的永久代,永久代用来存储Class类、常量、方法描述等。在永久代主要回收废弃的常量和无用的类
  • JVM内存中的对象主要被分配到新生代的Eden区和ServivorFrom区,在少数情况下会被直接分配到老年代。
  • 在新生代的Eden区和ServivorFrom区的内存空间不足时会触发一次GC,该过程被称为MinorGC。 在MinorGC后,在Eden区和ServivorFrom区中存活的对象会被复制到ServivorTo区,然后Eden区和ServivorFrom区被清理。如果此时在ServivorTo区无法找到连续的内存空间存储某个对象,则将这个对象直接存储到老年代。若Servivor区的对象经过一次GC后仍然存活,则其年龄加1。在默认情况下,对象在年龄达到15时,将被移到老年代

7、Java中的4中引用类型

  1. 强引用:在Java中最常见的就是强引用。在把一个对象赋给一个引用变量时,这个引用变量就是一个强引用;有强引用的对象一定为可达性状态,所以不会被垃圾回收机制回收。因此,强引用是造成Java内存泄漏(Memory Link)的主要原因
  2. 软引用:软引用通过SoftReference类实现。如果一个对象只有软引用,则在系统内存空间不足时该对象将被回收
  3. 弱引用:弱引用通过WeakReference类实现,如果一个对象只有弱引用,则在垃圾回收过程中一定会被回收
  4. 虚引用:虚引用通过PhantomReference类实现,虚引用和引用队列联合使用,主要用于跟踪对象的垃圾回收状态

8、分代收集算法和分区收集算法

  1. 分代收集算法:JVM根据对象存活周期的不同将内存划分为新生代、老年代和永久代,并根据各年代的特点分别采用不同的GC算法
  2. 分区收集算法:分区算法将整个堆空间划分为连续的大小不同的小区域,对每个小区域都单独进行内存使用和垃圾回收,这样做的好处是可以根据每个小区域内存的大小灵活使用和释放内存
  3. 分区收集算法可以根据系统可接受的停顿时间,每次都快速回收若干个小区域的内存,以缩短垃圾回收时系统停顿的时间,最后以多次并行累加的方式逐步完成整个内存区域的垃圾回收

9、垃圾收集器

  • JVM针对新生代和老年代分别提供了多种不同的垃圾收集器
  • 针对新生代提供的垃圾收集器有Serial、ParNew、Parallel Scavenge
  • 针对老年代提供的垃圾收集器有Serial Old、Parallel Old、CMS
  • 还有针对不同区域的G1分区收集算法

1、Serial垃圾收集器: 单线程,复制算法

  • Serial垃圾收集器基于复制算法实现,它是一个单线程收集器,在它正在进行垃圾收集时,必须暂停其他所有工作线程,直到垃圾收集结束
  • 对于单CPU运行环境来说,没有线程交互开销,可以获得最高的单线程垃圾收集效率,因此Serial垃圾收集器是Java虚拟机运行在Client模式下的新生代的默认垃圾收集器。

2、ParNew垃圾收集器: 多线程,复制算法

  • ParNew垃圾收集器是Serial垃圾收集器的多线程实现,同样采用了复制算法,它采用多线程模式工作,除此之外和Serial收集器几乎一样
  • ParNew垃圾收集器在垃圾收集过程中会暂停所有其他工作线程,是Java虚拟机运行在Server模式下的新生代的默认垃圾收集器

3、Parallel Scavenge垃圾收集器: 多线程,复制算法

  • Parallel Scavenge收集器是为提高新生代垃圾收集效率而设计的垃圾收集器,基于多线程复制算法实现,在系统吞吐量上有很大的优化,可以更高效地利用CPU尽快完成垃圾回收任务

4、Serial Old垃圾收集器: 单线程,标记整理算法

  • Serial Old垃圾收集器是Serial垃圾收集器的老年代实现,同Serial一样采用单线程执行,不同的是,Serial Old针对老年代长生命周期的特点基于标记整理算法实现
  • Serial Old垃圾收集器是JVM运行在Client模式下的老年代的默认垃圾收集器。

5、Parallel Old垃圾收集器: 多线程,标记整理算法

  • Parallel Old垃圾收集器采用多线程并发进行垃圾回收,它根据老年代长生命周期的特点,基于多线程的标记整理算法实现

6、CMS垃圾收集器

  • CMS(Concurrent Mark Sweep)垃圾收集器是为老年代设计的垃圾收集器
  • 其主要目的是达到最短的垃圾回收停顿时间,基于线程的标记清除算法实现,以便在多线程并发环境下以最短的垃圾收集停顿时间提高系统的稳定性

7、G1垃圾收集器

  • G1(Garbage First)垃圾收集器为了避免全区域垃圾收集引起的系统停顿,将堆内存划分为大小固定的几个独立区域,独立使用这些区域的内存资源并且跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,在垃圾回收过程中根据系统允许的最长垃圾收集时间,优先回收垃圾最多的区域
  • 相对于CMS收集器,G1垃圾收集器两个突出的改进:基于标记整理算法,不产生内存碎片;可以精确地控制停顿时间,在不牺牲吞吐量的前提下实现短停顿垃圾回收

10、网络编程模型

1、阻塞I/O模型

  • 阻塞I/O模型的工作流程为:在用户线程发出I/O请求之后,内核会检查数据是否就绪,此时用户线程一直阻塞等待内存数据就绪;在内存数据就绪后,内核将数据复制到用户线程中,并返回I/O执行结果到用户线程,此时用户线程将解除阻塞状态并开始处理数据
  • 典型的阻塞I/O模型的例子为data = socket.read(),如果内核数据没有就绪,Socket线程就会一直阻塞在read()中等待内核数据就绪

2、非阻塞I/O模型

  • 非阻塞I/O模型指用户线程在发起一个I/O操作后,无须阻塞便可以马上得到内核返回的一个结果
  • 如果内核返回的结果为false,则表示内核数据还没准备好,需要稍后再发起I/O操作。一旦内核中的数据准备好了,并且再次收到用户线程的请求,内核就会立刻将数据复制到用户线程中并将复制的结果通知用户线程

3、多路复用I/O模型

  • 在多路复用I/O模型中会有一个被称为Selector的线程不断轮询多个Socket的状态,只有在Socket有读写事件时,才会通知用户线程进行I/O读写操作。
  • 多路复用I/O模型是多线程并发编程用得较多的模型,Java NIO就是基于多路复用I/O模型实现的
  • 在实际应用中,在多路复用方法体内一般不建议做复杂逻辑运算,只做数据的接收和转发,将具体的业务操作转发给后面的业务线程处理

4、信号驱动I/O模型

  • 在信号驱动I/O模型中,在用户线程发起一个I/O请求操作时,系统会为该请求对应的Socket注册一个信号函数,然后用户线程可以继续执行其他业务逻辑;
  • 在内核数据就绪时,系统会发送一个信号到用户线程,用户线程在接收到该信号后,会在信号函数中调用对应的I/O读写操作完成实际的I/O请求操作

5、异步I/O模型

  • 在异步I/O模型中,用户线程会发起一个asynchronous read操作到内核,内核在接收到synchronous read请求后会立刻返回一个状态,来说明请求是否成功发起,在此过程中用户线程不会发生任何阻塞
  • 接着,内核会等待数据准备完成并将数据复制到用户线程中,在数据复制完成后内核会发送一个信号到用户线程,通知用户线程asynchronous读操作已完成

6、Java NIO

  • Java NIO的实现主要涉及三大核心内容:Selector(选择器)、Channel(通道)和Buffer(缓冲区)
  • 传统I/O基于数据流进行I/O读写操作;而Java NIO基于Channel和Buffer进行I/O读写操作,并且数据总是被从Channel读取到Buffer中,或者从Buffer写入Channel中
  • Channel和I/O中的Stream(流)类似,只不过Stream是单向的,而Channel是双向的,既可以用来进行读操作,也可以用来进行写操作。
  • Buffer实际上是一个容器,其内部通过一个连续的字节数组存储I/O上的数据
  • Selector用于检测在多个注册的Channel上是否有I/O事件发生,并对检测到的I/O事件进行相应的响应和处理

11、JVM的类加载机制

1、JVM的类加载阶段: 加载、验证、准备、解析、初始化。

  • 加载:类加载过程主要包含将Class文件读取到运行时区域的方法区内,在堆中创建java.lang.Class对象,并封装类在方法区的数据结构的过程
  • 验证:主要用于确保Class文件符合当前虚拟机的要求,保障虚拟机自身的安全,只有通过验证的Class文件才能被JVM加载
  • 准备:主要工作是在方法区中为类变量分配内存空间并设置类中变量的初始值
  • 解析:JVM会将常量池中的符号引用替换为直接引用
  • 初始化:主要通过执行类构造器的方法为类进行初始化。方法是在编译阶段由编译器自动收集类中静态语句块和变量的赋值操作组成的。JVM规定,只有在父类的方法都执行成功后,子类中的方法才可以被执行;在一个类中既没有静态变量赋值操作也没有静态语句块时,编译器不会为该类生成方法

2、类加载器: 启动类加载器、扩展类加载器和应用程序类加载器

  • 启动类加载器:负责加载Java_HOME/lib目录中的类库,或通过-Xbootclasspath参数指定路径中被虚拟机认可的类库
  • 扩展类加载器:负责加载Java_HOME/lib/ext目录中的类库,或通过java.ext.dirs系统变量加载指定路径中的类库
  • 应用程序类加载器:负责加载用户路径(classpath)上的类库

3、双亲委派机制

  • JVM通过双亲委派机制对类进行加载。双亲委派机制指一个类在收到类加载请求后不会尝试自己加载这个类,而是把该类加载请求向上委派给其父类去完成,其父类在接收到该类加载请求后又会将其委派给自己的父类,以此类推,这样所有的类加载请求都被向上委派到启动类加载器中
    在这里插入图片描述

4、OSGI

  • OSGI(Open Service Gateway Initiative)是Java动态化模块化系统的一系列规范,旨在为实现Java程序的模块化编程提供基础条件
  • 基于OSGI的程序可以实现模块级的热插拔功能,在程序升级更新时,可以只针对需要更新的程序进行停用和重新安装,极大提高了系统升级的安全性和便捷性

参考

  1. 书籍:《Offer来了》

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c盘爆满--如何清理电脑C盘

问题 c盘饱满很多天了,今天终于忍无可忍,开始展开对c盘的处理 c盘的基本处理有两步, 第一步,电脑系统清理 1,c盘右键属性,有个磁盘清理,好像是系统更新的一些缓存资源,可以直接清理 当然这只…

Hadoop MapReduce

目录1.1 MapReduce介绍1.2 MapReduce优缺点MapReduce实例进程阶段组成1.3 Hadoop MapReduce官方示例案例:评估圆周率π(PI)的值案例:wordcount单词词频统计1.4 Map阶段执行流程1.5 Reduce阶段执行流程1.6 Shuffle机制1.1 MapReduc…

BigScience bloom模型

简介项目叫 BigScience,模型叫 BLOOM,BLOOM 的英文全名代表着大科学、大型、开放科学、开源的多语言语言模型。拥有 1760 亿个参数的模型.BLOOM 是去年由 1000 多名志愿研究人员,学者 在一个名为“大科学 BigScience”的项目中创建的.BLOOM 和今天其他可用大型语言模型存在的一…

信号的FFT变换与加窗

1. fft 傅里叶变换 1.1 傅里叶变换的本质 数学上有一种公式叫做 泰勒展开: 泰勒公式: 其表达的思想,是任意一函数可以有多个指数函数构成 当指数函数的个数趋近于无穷多个,那么组合出来的函数将会逼近原函数; …

Pandas数据查询

Pandas数据查询 Pandas查询数据的几种方法 df.loc方法,根据行、列的标签值查询 df.iloc方法,根据行、列的数字位置查询 df.where方法 df.query方法 .loc既能查询,又能覆盖写入,强烈推荐! Pandas使用df.loc查询数据…

深度学习基础(二)-学习是怎么个回事

深度学习基础(一) 引入了一个 helloworld,提出了神经网络的简单关系,也就是一个基础公式 a(L) Sigmoid( a(L-1)*W(L) b(L)) a(L): 第L层神经元被激活之后 进行Sigmoid函数收敛 得到的值 b(L): 第L层神经元被激活阈值 W(L): 第L层神经元 与 第L-1层…

Android安卓中jni封装代码打包为aar

前文【Android安卓中jni与Java之间传递复杂的自定义数据结构】已经介绍jni编译c++代码且已经成功封装成java,但是c++是以源代码形式继承在app中,本文介绍如何将前述jni c++代码以隐藏源代码封装成aar的形式。 1、aar打包 1.1、新建module 按照流程 File -> New Module …

学习周报2.26

文章目录前言文献阅读摘要方法结果深度学习Encoder-Decoder(编码-解码)信息丢失的问题Attention机制总结前言 This week,I read an article about daily streamflow prediction.This study shows the results of an in-depth comparison between two di…

Oracle-RAC集群主机重启问题分析

问题背景: 在对一套两节点Oracle RAC19.18集群进行部署时,出现启动数据库实例就会出现主机出现重启的情况,检查发现主机重启是由于节点集群被驱逐导致​。 问题: 两节点Oracle RAC19.18集群,启动数据库实例会导致主机出现重启。 问题分析: 主机多次出现…

2023年第八周总周结 | 开学倒数第一周

为什么要做周总结? 1.避免跳相似的坑 2.客观了解上周学习进度并反思,制定可完成的下周规划 一、上周存在问题 发现自己反复犯同样问题,不想反思就不会意识到。总想以面带点的学习,实际上却在原地踏步。问题导向使用ChatGPT&#…

目标检测:DETR详解

1. 概述 DETR: End-to-End Object Detection with Transformers, DETR 是 Facebook 团队于 2020 年提出的基于 Transformer 的端到端目标检测,是Transformer在目标检测的开山之作 – DEtection TRansformer。 相比于传统的Faster-rcnn,yolo系列,DETR有以下几个优点:1).无需…

微信实时音视频通话数据流分析

一、实时音视频的架构 实时音视频通信架构主要包括P2P、SFU、MCU三种方式,其中点对点通信通常以P2P优先,P2P走不通的场景再借助于SFU/MCU。 P2P方式,终端之间点对点的相互收发数据流,音视频流不经过服务器; SFU是端侧…

scrapy下载图片

🐱 个人主页:莎萌玩家🙋‍♂️ 作者简介:全栈领域新星创作者、专注于全栈各领域技术,共同学习共同进步,一起加油呀!💫系列专栏:网络爬虫、WEB全栈开发📢 资料…

二叉树的后序遍历-java递归+非递归-力扣145双百方案

一、题目描述给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。示例 1:输入:root [1,null,2,3]输出:[3,2,1]示例 2:输入:root []输出:[]示例 3:输入:root [1]…

使用jenkins实现自动化部署springboot应用

1. 前置准备 这里代码仓库使用gitlab。在介绍如何通过gitlab和jenkins进行自动化部署之前,需要先安装完成gitlab以及jenkins。两种程序的安装方式以及相关配置可以参看以下内容: linux中安装gitlab:linux安装极狐gitlab linux中安装jenki…

Objective-C description 自定义对象的打印格式/输出的字符串 类似于Java 中的 toString 方法

总目录 iOS开发笔记目录 从一无所知到入门 文章目录IntroNSObject 源码测试类截图测试代码输出Intro 在 Java 中,对于自定义类一般会重写集成自Object类的toString方法,这样在打印该类的对象时,打印出的字符串就是我们在 toString() 方法中返…

【Vue3源码】第六章 computed的实现

【Vue3源码】第六章 computed的实现 上一章节我们实现了 ref 及其它配套的isRef、unRef 和 proxyRefs API。这一章开始实现computed计算属性。 认识computed 接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。…

[架构之路-121]-《软考-系统架构设计师》-计算机体系结构 -3-汇编语言与ARM系统的初始化

第9章 计算机体系结构 第1-6节 参考前文第7节 ARM汇编语言7.1 程序框架(1)数据段Data初始化的数据: 初始的全局变量未初始化的数据:未初始化的全局变量堆heap:malloc的内存或数据栈stack:函数的局部变量&am…

ubuntu20系统+RobotiQ 2F-85夹爪+Ros+VMware配置

文章目录环境说明Ros配置Vmware虚拟机串口通信配置运行节点并调试有关问题解决办法rosdep相关缺少ros有关的库与pymodbus相关参考环境说明 环境说明系统版本Ubuntu 20.04.4Ros版本noetic主机形式VMware虚拟机夹爪型号RobotiQ 2F-85 Ros配置 新建ros工作空间并进行初始化 mkdir…

Nginx配置web服务器及部署反向代理

Nginx配置web服务器及部署反向代理配置web服务器location语法部署反向代理代理转发配置web服务器 项目部署到linux上的静态文件代理给Nginx处理。当访问服务器IP时,可以自动返回静态文件主页。 主配置文件中server块对应的次配置include /etc/nginx/conf.d/*.conf…