黑马JVM学习笔记-内存结构

news2025/7/15 22:53:28

什么是JVM?

定义:

Java Virtual Machine - java 程序的运行环境(Java二进制字节码的运行环境)

好处:3

  • 一次编写,到处运行
  • 自动内存管理,垃圾回收功能
  • 数组下标越界检查(下标越界抛出异常比数组新元素覆盖其他部分造成的危害小)
  • 多态(面向对象编程的基石,jvm内部采用虚方法表的方式实现多态)

比较:

jvm jre jdk

请添加图片描述

jvm屏蔽Java代码与底层操作系统之间的差异

jdk+集成开发工具->JavaSE

jdk+应用服务器(如:tomcat)+集成开发工具->JavaEE

学习JVM有什么用?

  • 面试!!!
  • 理解底层的实现原理
  • 中高级程序员的必备技能

常见的JVM有哪些?

请添加图片描述

学习路线

请添加图片描述

方法执行时的每行代码是由执行引擎中的解释器逐行进行执行

方法里面的热点代码(频繁执行的代码)由执行引擎的即时编译器编译

GC:会对堆里面不再被引用的对象进行回收

内存结构

1.程序计数器

请添加图片描述

1.1定义

Program Counter Register程序计数器(寄存器)

  • 作用,是记住下一条jvm指令的执行地址
  • 特点
    • 是线程私有的
    • 唯一 一个不会存在内存溢出

1.2作用

二进制字节码 jvm指令 java源代码

0: getstatic #20            // PrintStream out = System.out;
3: astore_1                 // --
4: aload_1                  // out.println(1);
5: iconst_1                 // --
6: invokevirtual #26        // --
9: aload_1                  // out.println(2);
10: iconst_2                // --
11: invokevirtual #26       // --
14: aload_1                 // out.println(3);
15: iconst_3                // --
16: invokevirtual #26       // --
19: aload_1                 // out.println(4);
20: iconst_4                // --
21: invokevirtual #26       // --
24: aload_1                 // out.println(5);
25: iconst_5                // --
26: invokevirtual #26       // --
29: return

二进栈字节码 经过解释器 变成机器码 交给cpu执行

程序计数器负责将下一条jvm指令的执行地址告诉解释器

程序计数器在物理上是通过寄存器实现的

2.虚拟机栈

栈:先进后出

请添加图片描述

2.1定义:

请添加图片描述

Java Virtual Machine Stacks (Java 虚拟机栈)

  • 每个线程运行时需要的内存,称为虚拟机栈
  • 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
  • 每个线程只有一个活动栈帧,对应着当前正在执行的那个方法

问题辨析

  1. 垃圾回收是否涉及栈内存?

    • 栈帧内存每次方法调用结束后都会弹出栈;不涉及
  2. 栈内存分配越大越好吗?

    • 不是

    • 运行java代码时可以通过-Xss size给栈内存指定大小

    请添加图片描述

    • 栈内存分配越大(只是能更多次的进行方法调用),线程数越少
  3. 方法内的局部变量是否线程安全?

    • 如果方法内局部变量没有逃离方法的作用访问,它是线程安全的
    • 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全
    • 共享的需要考虑线程安全,私有的不需要考虑线程安全

2.2栈内存溢出

java.lang.StackOverflowError

  • 栈帧过多导致栈帧内层溢出
  • 栈帧过大导致栈内层溢出

2.3线程运行诊断

案例1: cpu 占用过多

定位

  • 用top定位哪个进程对cpu的占用过高
  • ps H -eo pid,tid,%cpu | grep 进程id (用ps命令进一步定位是哪个线程引起的cpu占用过高;H:打印进程数;-eo:规定哪些感兴趣的内容:pid:进程id、tid:线程id, %cpu:对cpu的占用;grep:进行筛选)
  • jstack 进程id
    • 可以根据线程id 找到有问题的线程,进一步定位到问题代码的源码行号

案例2:程序运行很长时间没有结果

  • 如:死锁

3.本地方法栈

java虚拟机调用本地方法(不是由Java编写的代码)时,需要给本地方法提供的内层空间

  • Object里面:clone()方法、hashCode()、notify()、wait()等都是native的

请添加图片描述

4.堆

  • 前面都是线程私有的,堆是线程共享的

请添加图片描述

4.1定义

Heap 堆

  • 通过new关键字,创建对象都会使用堆内层

特点

  • 它是线程共享的,堆中对象都需要考虑线程安全的问题
  • 有垃圾回收机制

4.2 堆内存溢出

  • -Xmx8m:可以改变堆内存空间大小8m :代表8兆默认4g

  • java.lang.OutOfMemoryError: java heap space

堆内存中的对象只有不再有人使用了才会被当做垃圾回收,如果不断产生对象且一直有人使用它们,就意味着这些对象不能成为垃圾,当这些对象达到一定的数量,堆内存就会被耗尽

int i=0;
try{
    Lsit<String> list = new ArrayList<>();
    String a="hello";
    while(true){
        list.add(a);//hello
        a = a+a;    //hellohello
        i++;
    }
}catch(Throwable e){
    e.printStackTrace();
    System.out.println(i);
}

4.3 堆内存诊断

1.jps工具

  • 查看当前系统中有哪些Java程序

2.jmap工具

  • 查看堆内存占用情况(某个时刻的) jamp -heap进程id

3.jconsole工具

  • 图形界面的,多功能的监测工具,可以连续监测

案例

  • 垃圾回收后,内存占用仍然很高

5.方法区

请添加图片描述

5.1定义

JVM规范-方法区定义

Chapter 2. The Structure of the Java Virtual Machine (oracle.com)

  • 所有Java虚拟机线程共享的一块区域
  • 这块区域存储了跟类的结构相关的信息:成员变量、方法、成员方法以及构造器方法、运行时常量池
  • 在虚拟机启动时被创建,逻辑上是堆的一个组成部分

永久代是jdk1.8以前方法区的一个实现

5.2 组成

请添加图片描述

1.8已经不再由jvm管理其内存结构了,已经被移出到本地内存当中 (操作系统内存)

JDK1.8版本之前方法区用的堆的内存,叫永久代,JDK1.8之后用的操作系统的内存,叫元空间

这里说的不对,StringTable一直都在本地内存,StringTable中存储的是对字符串对象的指针,对应的String对象在堆中

请添加图片描述

5.3方法区内存溢出

  • 1.8 以前会导致永久代内存溢出
* 演示永久代内存溢出 java.lang.OutOfMemoryError: PermGen space
* -XX:MaxPermSize=8m
  • 1.8 之后会导致元空间内存溢出
* 演示元空间内存溢出 java.lang.OutOfMemoryError: Metaspace
* -XX:MaxMetaspaceSize=8m

场景

  • spring

  • mybatis

5.4 运行时常量池

  • 常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量 等信息
  • 运行时常量池,常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量 池,并把里面的符号地址变为真实地址

5.5 StringTable(串池)

先看几道面试题:

String s1 = "a";
String s2 = "b";
String s3 = "a" + "b";//编译期优化为ab,常量池没有所以放入常量池
String s4 = s1 + s2;//new String("ab")
String s5 = "ab";
String s6 = s4.intern();
 
// 问
System.out.println(s3 == s4);//false
System.out.println(s3 == s5);//true
System.out.println(s3 == s6);//true
String x2 = new String("c") + new String("d");//new String("cd")
String x1 = "cd";
x2.intern();//没入池成功

// 问,如果调换了【最后两行代码】的位置呢?:true,如果是jdk1.6呢false
System.out.println(x1 == x2);//false
package cn.itcast.jvm.t1.stringtable;

// StringTable [ "a", "b" ,"ab" ]  hashtable 结构,不能扩容
public class Demo1_22 {
    // 常量池中的信息,都会被加载到运行时常量池中, 这时 a b ab 都是常量池中的符号,还没有变为 java 字符串对象
    // ldc #2 会把 a 符号变为 "a" 字符串对象
    // ldc #3 会把 b 符号变为 "b" 字符串对象
    // ldc #4 会把 ab 符号变为 "ab" 字符串对象

        public static void main(String[] args) {
            String s1 = "a"; // 懒惰的
            String s2 = "b";
            String s3 = "ab";
            String s4 = s1 + s2; // new StringBuilder().append("a").append("b").toString()  new String("ab")
            String s5 = "a" + "b";  // javac 在编译期间的优化,结果已经在编译期确定为ab

            System.out.println(s3 == s5);
        }
}

5.5 StringTable特性

  • 常量池中的字符串仅是符号,第一次用到时才变为对象
  • 利用串池的机制,来避免重复创建字符串对象
  • 字符串变量拼接的原理是 StringBuilder (1.8)
  • 字符串常量拼接的原理是编译期优化
  • 可以使用 intern 方法,主动将串池中还没有的字符串对象放入串池
    • 1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串 池中的对象返回
    • 1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份, 放入串池, 会把串池中的对象返回
/**
 * 演示字符串字面量也是【延迟】成为对象的
 */
public class TestString {
    public static void main(String[] args) {
        int x = args.length;
        System.out.println(); // 字符串个数 2275

        System.out.print("1");
        System.out.print("2");
        System.out.print("3");
        System.out.print("4");
        System.out.print("5");
        System.out.print("6");
        System.out.print("7");
        System.out.print("8");
        System.out.print("9");
        System.out.print("0");
        System.out.print("1"); // 字符串个数 2285
        System.out.print("2");
        System.out.print("3");
        System.out.print("4");
        System.out.print("5");
        System.out.print("6");
        System.out.print("7");
        System.out.print("8");
        System.out.print("9");
        System.out.print("0");
        System.out.print(x); // 字符串个数
    }
}

JDK1.8

情况一:
public class Demo1_23 {
    //  ["ab", "a", "b"]
    public static void main(String[] args) {
        String s = new String("a") + new String("b");//在堆中

        // 堆  new String("a")   new String("b") new String("ab")
        String s2 = s.intern(); // 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串池中的对象返回

        System.out.println( s2 == "ab");//true
        System.out.println( s == "ab" );//true
    }
}
情况二:
public class Demo1_23 {
    //  ["ab", "a", "b"]
    public static void main(String[] args) {
        String x = "ab";
        String s = new String("a") + new String("b");//在堆中
        // 堆  new String("a")   new String("b") new String("ab")
        String s2 = s.intern(); // 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串池中的对象返回
        System.out.println( s2 == "ab");//true
        System.out.println( s == "ab" );//false
    }
}

JDK1.6

public class Demo1_23 {

    // ["a", "b", "ab"]
    public static void main(String[] args) {


        String s = new String("a") + new String("b");

        // 堆  new String("a")   new String("b")  new String("ab")
        String s2 = s.intern(); // 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串池中的对象返回
        // s 拷贝一份,放入串池

        String x = "ab";
        System.out.println( s2 == x);//true
        System.out.println( s == x );//false
    }
}

    //["ab","a","b"]
    public static void main(String[] args) {

         String x = "ab";
        String s = new String("a") + new String("b");

        // 堆  new String("a")   new String("b")  new String("ab")
        String s2 = s.intern(); // s2,是串池中原有的ab,s是堆中的
        System.out.println( s2 == x);//true
        System.out.println( s == x );//false
    }
}


5.6 StringTable 位置

请添加图片描述

改变的原因:永久代的回收效率很低,永久代只有fullGC 的时候才会垃圾回收,而FUll GC 的触发条件是老年代空间不足,发生的时机晚。而StringTable的使用又比较频繁所以就会占用大量的内存,进而导致永久代内存不足

**证明方式:**不断的往StringTable里存放大量的字符串对象,并且用一个长时间存活的对象引用它,这样肯定会造成空间不足,如果在jdk1.6就会报永久代的内存空间不足(PermGen space),如果在jdk1.7及以上就会报堆空间不足(Java heap space)

/**
 * 演示 StringTable 位置
 * 在jdk8下设置 -Xmx10m -XX:-UseGCOverheadLimit一个开关
 * 在jdk6下设置 -XX:MaxPermSize=10m
 */
public class Demo1_6 {

    public static void main(String[] args) throws InterruptedException {
        List<String> list = new ArrayList<String>();
        int i = 0;
        try {
            for (int j = 0; j < 260000; j++) {
                list.add(String.valueOf(j).intern());//intern()就是让其存入StringTable
                i++;
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            System.out.println(i);
        }
    }
} 

5.7 StringTable 垃圾回收

从以下案例中可以看出StringTable是存在垃圾回收的

/**
 * 演示 StringTable 垃圾回收
 *  虚拟机堆内存的最大值 打印字符串表的统计信息           打印垃圾回收的详细信息
 * -Xmx10m            -XX:+PrintStringTableStatistics -XX:+PrintGCDetails -verbose:gc
 */
public class Demo1_7 {
    public static void main(String[] args) throws InterruptedException {
        int i = 0;
        try {
            for (int j = 0; j < 100000; j++) { // j=100, j=10000
                String.valueOf(j).intern();
                i++;
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            System.out.println(i);
        }

    }
}


[GC (Allocation Failure) [PSYoungGen: 2048K->488K(2560K)] 2048K->756K(9728K), 0.0027377 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2536K->424K(2560K)] 2804K->700K(9728K), 0.0132936 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2472K->424K(2560K)] 2748K->700K(9728K), 0.0026577 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
100000
Heap
 PSYoungGen      total 2560K, used 1432K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 49% used [0x00000000ffd00000,0x00000000ffdfc240,0x00000000fff00000)
  from space 512K, 82% used [0x00000000fff00000,0x00000000fff6a020,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 276K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 3% used [0x00000000ff600000,0x00000000ff645010,0x00000000ffd00000)
 Metaspace       used 3222K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 350K, capacity 388K, committed 512K, reserved 1048576K
SymbolTable statistics:
Number of buckets       :     20011 =    160088 bytes, avg   8.000
Number of entries       :     13234 =    317616 bytes, avg  24.000
Number of literals      :     13234 =    566288 bytes, avg  42.790
Total footprint         :           =   1043992 bytes
Average bucket size     :     0.661
Variance of bucket size :     0.662
Std. dev. of bucket size:     0.813
Maximum bucket size     :         6
StringTable statistics:
Number of buckets       :     60013 =    480104 bytes, avg   8.000
Number of entries       :     19582 =    469968 bytes, avg  24.000
Number of literals      :     19582 =   1155792 bytes, avg  59.023
Total footprint         :           =   2105864 bytes
Average bucket size     :     0.326
Variance of bucket size :     0.341
Std. dev. of bucket size:     0.584
Maximum bucket size     :         4

Process finished with exit code 0

5.8 StringTable 性能调优

  • 调整 -XX:StringTableSize=桶个数
  • 考虑将字符串对象是否入池

如果有大量的重复字符串可以让字符串入池来减少字符串的个数减少堆内存的使用

/**
 * 演示 intern 减少内存占用
 * -XX:StringTableSize=200000 -XX:+PrintStringTableStatistics
 * -Xsx500m -Xmx500m -XX:+PrintStringTableStatistics -XX:StringTableSize=200000
 */
public class Demo1_25 {
    public static void main(String[] args) throws IOException {
        List<String> address = new ArrayList<>();
        System.in.read();
        for (int i = 0; i < 10; i++) {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
                String line = null;
                long start = System.nanoTime();
                while (true) {
                    line = reader.readLine();
                    if(line == null) {
                        break;
                    }
                    address.add(line.intern());
                }
                System.out.println("cost:" +(System.nanoTime()-start)/1000000);
            }
        }
        System.in.read();
    }
}

6.直接内存

不属于Java虚拟机的内存管理而是属于系统内存(操作系统内存)

垃圾回收不会管理直接内存

6.1 定义

Direct Memory

  • 常见于NIO操作时,NIO读写时用于数据缓冲区
  • 分配回收成本较高,但读写性能高
  • 不受JVM内存回收管理
/**
 * 演示 ByteBuffer 作用
 */
public class Demo1_9 {
    static final String FROM = "E:\\编程资料\\第三方教学视频\\youtube\\Getting Started with Spring Boot-sbPSjI4tt10.mp4";
    static final String TO = "E:\\a.mp4";
    static final int _1Mb = 1024 * 1024;

    public static void main(String[] args) {
        io(); // io 用时:1535.586957 1766.963399 1359.240226
        directBuffer(); // directBuffer 用时:479.295165 702.291454 562.56592
    }

    private static void directBuffer() {
        long start = System.nanoTime();
        try (FileChannel from = new FileInputStream(FROM).getChannel();
             FileChannel to = new FileOutputStream(TO).getChannel();
        ) {
            ByteBuffer bb = ByteBuffer.allocateDirect(_1Mb);
            while (true) {
                int len = from.read(bb);
                if (len == -1) {
                    break;
                }
                bb.flip();
                to.write(bb);
                bb.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("directBuffer 用时:" + (end - start) / 1000_000.0);
    }

    private static void io() {
        long start = System.nanoTime();
        try (FileInputStream from = new FileInputStream(FROM);
             FileOutputStream to = new FileOutputStream(TO);
        ) {
            byte[] buf = new byte[_1Mb];
            while (true) {
                int len = from.read(buf);
                if (len == -1) {
                    break;
                }
                to.write(buf, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("io 用时:" + (end - start) / 1000_000.0);
    }
}

java本身不具有磁盘读写的能力,需要调用操作系统的函数(本地方法)

所以这里会涉及到CPU的状态从用户态切换为内核态,然后就由cpu的函数去读取磁盘文件的内容,读取之后在内核态的时候会在操作系统内存中划出一块系统缓存区(系统缓存区Java代码不能运行),所以Java会在堆内存中分配一块Java缓冲区,Java代码要想读取的流中的数据必须从系统缓存区把数据间接的读入到Java缓冲区,cpu会再进入用户态,之后再去调输出流的写入操作

出现的问题:

  • 读取的时候数据存了两份,造成了不必要的数据的复制

请添加图片描述

调用ByteBuffer的allocateDirect(): 分配一块直接内存

这个方法调用之后意味着会在操作系统里面划出一块缓冲区(direct memory),这块操作系统划出的区域Java代码可以直接访问——换句话说这块内存系统可以用,Java代码也可以用

好处:

  • 少了一次缓冲区的复制操作,速度就更快

请添加图片描述

**存在内存溢出:**java.lang.OutOfMemoryError: Direct buffer memory

/**
 * 演示直接内存溢出
 */
public class Demo1_10 {
    static int _100Mb = 1024 * 1024 * 100;

    public static void main(String[] args) {
        List<ByteBuffer> list = new ArrayList<>();
        int i = 0;
        try {
            while (true) {
                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100Mb);
                list.add(byteBuffer);
                i++;
            }
        } finally {
            System.out.println(i);
        }
        // 方法区是jvm规范, jdk6 中对方法区的实现称为永久代
        //                  jdk8 对方法区的实现称为元空间
    }
}

6.2 分配和回收原理

  • 使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法
  • ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦 ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程(守护线程)通过 Cleaner 的 clean 方法调 用 freeMemory 来释放直接内存

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

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

相关文章

1. SAP Business Application Studio 里创建一个基于 CAP 模型的最简单的 OData 服务

本教程已经花费了 24 个文章的篇幅,介绍了使用 SAP ABAP SEGW 这个开发工具,开发基于 SAP ABAP 技术栈的 OData 服务的详细步骤。 正如本教程目录 中提到的那样,SAP OData 开发技术包含传统的 ABAP,RAP(Restful ABAP Programming) 和 CAP(Cloud Application Programming) …

前端程序员接私活,直呼赚麻了

总有一些前端程序员会想找私活&#xff0c;但是又不清楚具体的办法&#xff0c;或者是做了但没完全做&#xff0c;吃力又不讨好还赚不到钱。今天就给大家介绍一些可行性高的方法&#xff0c;让你快速找到合适的前端兼职。 干货满满&#xff0c;希望大家点赞收藏下&#xff0c;别…

Java 异常中 e.getMessage() 和 e.toString() e.printStackTrace()的区别常见的几种异常

Java 异常中 e.getMessage() 和 e.toString() e.printStackTrace()的区别 一、概述 在java异常体系中&#xff0c;要打印异常信息&#xff0c;可以通过&#xff1a;e.getMessage() 、 e.toString() e.printStackTrace() 等方法打印出 一些 异常信息。已知的是这些方法都可以打…

WinBUGS对多元随机波动率模型:贝叶斯估计与模型比较

在本文中&#xff0c;我们通过一个名为WinBUGS的免费贝叶斯软件&#xff0c;可以很容易地完成基于似然的多变量随机波动率&#xff08;SV&#xff09;模型的估计和比较。 最近我们被客户要求撰写关于随机波动率的研究报告&#xff0c;包括一些图形和统计输出。通过拟合每周汇率…

机器学习笔记之贝叶斯线性回归(一)线性回归背景介绍

机器学习笔记之贝叶斯线性回归——线性回归背景介绍引言回顾&#xff1a;线性回归场景构建从概率密度函数认识最小二乘法回顾&#xff1a;最小二乘估计回顾&#xff1a;线性回归与正则化关于线性回归的简单小结贝叶斯线性回归贝叶斯方法贝叶斯方法在线性回归中的任务贝叶斯线性…

kubernetes深入理解Pod对象之调度篇

目录 一、Pod调度流程 二、 容器资源限制 2.1 内存和CPU限制 三、 NodeSelector 四、NodeAffinity 4.1 基本概念 4.2 Pod 示例 4.2.1使用首选的节点亲和性调度 Pod 4.2.2依据强制的节点亲和性调度 Pod 五、Taints与Tolerations 5.1 基本概念 5.2Taints与Toleratio…

Ceph块存储

目录 一、环境准备 二、什么是块存储 三、创建块共享 1、查看存储池 2、创建镜像、查看镜像 3、镜像扩容、缩容 四、客户端通过KRBD访问共享镜像 1、客户端安装 2、客户端配置 3、客户端获取镜像 4、客户端写入数据 五、快照 1、查看、创建快照 2、还原快照 六、…

shell实战案例:系统性能监控脚本

一 简介 下面我们来编写一个检测系统环境、监控系统性能的脚本&#xff0c;并判断各项数据指标是否符合预设的阈值。如果数据有异常&#xff0c;就报警&#xff0c;如何报警&#xff0c;视情况而定。注意脚本中的很多预设值只是假设值&#xff0c;在实际生产环境中还需要根据业…

cubeIDE开发, 物联网应用之stm32的蓝牙通信设计

一、蓝牙通信技术 蓝牙技术是一种点对点点对面的网络构架&#xff0c;他可以在限制的范围内以很快的速度传输网络数据&#xff0c;在物联网应用中&#xff0c;支持网状网络的物联网短距离无线通信。目前它还被广泛用于智能可穿戴设备、智能门锁、智能医疗设备、智能照明设备、智…

十二、CANdelaStudio入门-Security

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的Security概念,欢迎各位朋友订阅、评论,…

【GamePlay】Unity手机屏幕UI适配问题

前言 关于UI不同分辨率适配问题和摄像机视口的注意事项 画布大小与锚点 首先要了解这两个东西 对于画布大小&#xff0c;主要理解match的含义&#xff0c;滑到Width时&#xff0c;表示以宽度为基准&#xff0c;Width不变&#xff0c;Height根据真机分辨率改变。 比如自己设…

pytest测试框架搭建

文章目录一、pytest是什么&#xff1f;二、pytest的特点三、pytest下载安装四、pytest的配置五、pytest约束规则六、编写脚本七、pytest的运行方式1、主函数模式2、命令行模式3、通过读取pytest ini配置文件运行 &#xff08;最主要运用的方式&#xff09;一、pytest是什么&…

【Unity】按Text文本内容自适应背景大小

按照文本内容自动调节背景框大小是十分方便的&#xff0c;本文章记录一下通过无代码方式实现该效果。&#xff08;版本Unity2018.4&#xff09; 目录 一、Text组件操作 二、Image组件操作 三、效果展示 一、Text组件操作 创建新的Text组件&#xff0c;然后进行下面操作&am…

LabVIEW避免在使用functional global时内存中有多个大数组的拷贝

LabVIEW避免在使用functional global时内存中有多个大数组的拷贝 有一个非常大的数组,但想保证在内存中只有一个拷贝.知道可以用移位寄存器,并用"ReplaceArray Subset" VI 保证只有一个拷贝。然而&#xff0c;想使之成为一个functionalglobal。因为&#xff0c;不能…

Ceph对象存储

目录 一、环境准备 二、什么是对象存储 三、部署对象存储服务 1、启动RGW服务 2、更改RGW服务端口 3、客户端测试 一、环境准备 Ceph集群搭建参照&#xff1a;Ceph集群部署_桂安俊kylinOS的博客-CSDN博客 以下Ceph存储实验环境均基于上述Ceph集群环境搭建。 二、什么是…

理解中国经济的五层思维-中国视角下的宏观经济

理解中国经济的五层思维 – 潘登同学的宏观经济学笔记 文章目录理解中国经济的五层思维 -- 潘登同学的宏观经济学笔记思想的力量理解中国经济的五层思维第一层思维&#xff1a;唯GDP论第二层思维&#xff1a;天真的市场派(新-新古典综合世界观对中国经济的影响)第三层思维&…

20221126给Chrome浏览器安装扩展程序——猫抓

20221126给Chrome浏览器安装扩展程序——猫抓 2022/11/26 21:43 百度&#xff1a;chrome 猫爪 https://www.onlinedown.net/soft/1232149.htm 猫抓 1.0.17 最新版 设置→ 01 百度搜索 QQ图片20221126214334.png 02 猫抓 QQ图片20221126214407.png 03 设置.png 04扩展程序.…

HTTP介绍报文格式构造

HTTP 一. 简单介绍一下: 二. 学习报文格式: 三. HTTP中的细节介绍 四, 如何构造一个HTTP请求 一. 简单介绍一下: 是应用层的典型协议客户端发送一个HTTP请求, 服务器返回一个HTTP响应(一问(请求)一答(响应)的)HTTP是文本格式的协议二. 学习报文格式: 1)先简单看一看HTTP的…

有监督学习神经网络的回归拟合——基于红外光谱的汽油辛烷值预测(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

2022年11月26日NaiveBayes

参考 ​ 朴素贝叶斯算法的核心思想是通过考虑特征概率来预测分类&#xff0c;即对于给出的待分类样本&#xff0c;求解在此样本出现的条件下各个类别出现的概率&#xff0c;哪个最大&#xff0c;就认为此待分类样本属于哪个类别。 ​ 我的理解是已知结果然后计算所有导致结果原…