JVM简单了解内存溢出

JVM

oracle官网文档:https://docs.oracle.com/en/java/javase/index.html

什么是JVM

JVM(Java Virtual Machine)原名Java虚拟机,是一个可以执行Java字节码的虚拟计算机。它的作用是在不同平台上实现Java程序的跨平台运行,即使在不同的硬件和操作系统上也能保持一致的行为。

JVM的结构和组成

JVM由类加载器、执行引擎、内存区域、本地方法接口等组成。

  1. 类加载器(ClassLoader):负责将java类文件加载到JVM中。Java类的加载过程分为加载、连接和初始化三个阶段。在加载阶段,类加载器将字节码文件加载到JVM中,并生成一个唯一的类标识符(Class Identifier)来代表该类。在连接阶段,JVM会将类的字节码文件校验、准备和解析为可以被JVM使用的数据结构。在初始化阶段,JVM会执行类的静态代码块,完成类的初始化工作。
  2. 执行引擎(Execution Engine):负责执行Java字节码文件。它将字节码文件解释为机器码或直接编译成本地代码来执行。在执行过程中,执行引擎会通过调用Java类库中的方法来实现不同的功能。
  3. 内存区域(Memory Area):JVM将内存划分为不同的区域,用于存放不同类型的数据。主要包括程序计数器、虚拟机栈、本地方法栈、堆区、方法区等。程序计数器用于记录当前线程执行的字节码指令的地址;虚拟机栈用于存放方法的调用栈帧,以及方法参数、局部变量等数据;本地方法栈用于支持本地方法的执行;堆区用于存放对象实例和数组等数据;方法区用于存储类的信息、常量池、静态变量、即时编译器编译后的代码等数据。
  4. 本地方法接口(Native Interface):允许Java代码调用本地代码。本地代码是指使用其他语言编写的代码,例如C、C++等。Java程序可以通过本地方法接口调用本地代码,实现更高效的计算和与外部系统的交互。

虚拟机类加载机制

Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称为虚拟机的类加载机制。

类加载器

Java虚拟机设计团队有意把类加载阶段中的“通过一个类的全限定名称来获取描述该类的二进制字节流”这个动作放到Java虚拟机外部实现,以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码被称为“类加载器”(Class Loader)。

类和类加载器

对于任意一个类,都必须由类加载器和这个类本身一起共同确定其在Java虚拟机的唯一性,每一个类加载器,都拥有一个独立的类名称空间。意思是:比较两个类是否“相等”,只要这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源同一个Class文件,被同一个Java虚拟机加载,只要加载他们的类加载器不同,那这两个类必然不相等。

相等包括Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,也包括使用instanceof关键字作为对象所属关系判定等多种情况。

/**
 * 类加载器和instanceof
 */
public class ClassLoaderTest {

    public static void main(String[] args) throws Exception {
        ClassLoader myClassLoader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String name) throws ClassNotFoundException {

                String fileName = name.substring(name.lastIndexOf(".") + 1)  + ".class";
                InputStream is = getClass().getResourceAsStream(fileName);
                if (is == null){
                    System.out.println("资源没有读取到");// // ClassLoaderTest之后还会加载java.lang.Object、java.lang.ClassLoader、匿名内部类加载(能找到)
                    return super.loadClass(name);
                }
                try {
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name,b,0,b.length);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

            }
        };
        Object obj = myClassLoader.loadClass("org.javaboy.vhr.ClassLoaderTest").newInstance();
        System.out.println(obj.getClass());
        System.out.println(obj instanceof org.javaboy.vhr.ClassLoaderTest);
    }
}

双亲委派模型

站在Java虚拟机的角度来看,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载使用C++语言实现(HotSpot书281),是虚拟机的一部分;另外一种就是其他的所有的类加载器,这些类加载器都是由Java语言实现,独立存在于虚拟机外部,并且全部继承自抽象类java.lang.ClassLoader。

自JDK1.2以来,Java一直保持者三层类加载器、双亲委派的类加载结构,尽管这套架构在Java模块化系统出现后有了一些调整变动,但依然没有改变其主体结构。

JDK8及之前版本所使用的三层类加载器:

  1. 启动类加载器(Bootstrap Class Loader):这个类加载器负责加载存放在<JAVA_HOME>\lib目录,或者-Xbootclasspath参数所指定的路径中存放的,而且是Java虚拟机能够识别的(按照文件名识别,如rt.jar、tools.jar,名字不符合的类库即使放到lib目录下也不会被加载)类库加载到虚拟机的内存中。启动类加载器无法被Java程序直接引用,用户在编写自定义类加载器时,如果需要把请求给启动类加载器去处理,那么直接使用null代替即可。
  2. 扩展类加载器(Extension Class Loader):这个类加载器时在类sun.misc.Launcher$ExtClassLoader中以Java代码实现。负责加载<JAVA_HOME>\lib\ext目录中或者被java.ext.dirs系统变量所指定的路劲中的所有类库。
  3. 应用程序类加载器(Application Class Loader):这个类加载器时由sun.miscLauncher$AppClassLoader来实现。负责加载classpath或java.class.path指定目录的类库。这个类加载器是ClassLoader类中getSystemClassLoader()方法的返回值。

双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。不过这里的类加载器之间的父子关系不是以继承(Inheritance)的方式实现的,而是通常以组合(Composition)关系来复用父加载器的代码。

双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己尝试去加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。

使用双亲委派模型来组织类加载器之间的关系,一个显而意见的好处就是Java中的类随着他的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存在rt.jar包中,无论哪一个类加载器去加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都能保证是同一个类。反之,如果没有使用双亲委派模型,都由各个类加载器自行去加载的话,如果用户自己也编写了一个名为java.lang.Object的类,并放在程序的ClassPath下,那系统就会出现多个不同的Object类,Java类型体系中最基本的行为也无法保证,应用程序会变得混乱。

实现双亲委派模型的代码

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
    // 加锁
    synchronized (getClassLoadingLock(name)) {
        // 首先,检查类是否已经加载
        Class<?> c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    // parent为null,代表它的父类是根加载器
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // 如果没有从非空父类加载器中找到类,则抛出ClassNotFoundException
            }
            if (c == null) {
                // 如果仍未找到,则调用findClass来查找该类。
                long t1 = System.nanoTime();
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

自定义类加载器

自定义类加载器可以实现一些特殊的需求,例如实现类的动态加载、实现类的隔离性、实现类的热替换等。

JDK1.2之前就有了就有了类加载器的概念和抽象类java.lang.ClassLoader就有了,JDK1.2之后才被引入双亲委派模型。设计者为了引入双亲委派模型不得不作出一些妥协,为了兼容已有的代码,无法再以技术手段避免loadClass()被子类覆盖的可能性,只能在JDK1.2之后的java.lang.ClassLoader中添加一个新的protected方法findClass(),并引导用户编写类加载逻辑时尽可能去重写这个方法,而不是在loadClass方法中编写代码。

类加载执行过程
  1. 加载:类加载器首先会检查是否已经加载了该类,如果已经加载了该类,则直接返回该类的Class对象;如果没有加载该类,则继续执行下一步操作。
  2. 连接:连接分为三个阶段:分别是验证、准备、解析。
    3. 验证阶段:验证该类是否符合Java虚拟机规范,主要检查该类文件的格式、语法和语义等方面。
    4. 准备阶段:为该类的静态变量分配内存,并设置默认值。
    4. 解析阶段:将该类的符号引用转换为直接引用。
  3. 初始化:类加载器会执行类的初始化代码,包括静态变量初始化和静态代码块的执行等。
类的初始化

《Java虚拟机规范》中并没有对什么情况下需要开始类加载过程的第一个阶段“加载”进行强制约束,但是对于初始化阶段,《Java虚拟机规范》则是严格规定了有且仅有六种情况必须对类进行“初始化”(加载、验证、准备自然需要在此之前开始):

  1. 遇到new、getstatic、putstatic、invokestatic这四条字节码指令,如果类型没有进行过初始化,则需要先触发其初始化阶段。
  2. 使用java.lang.reflect包的方法对类型进行方式调用的时候,如果类型没有进行过初始化,则需要先触发其初始化阶段。
  3. 当初始化类的时候,如果父类还没有进行过初始化,则需要先触发其父类的初始化。
  4. 当虚拟机启动时,用户指定的主类(包含main方法的类),虚拟机会先初始化这个主类。
  5. 使用JDK7新加入的动态语言支持,java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四种类型的方法句柄。
  6. 当一个接口中定义了JDK8新加入的默认方法,如果有这个接口的实现类发生了初始化,则这个接口先初始化。

类的初始化时类加载的最后一个步骤,Java虚拟机真正开始执行类中编写的代码(static{}块)。Java类中有变量的初始化或者静态代码块,就会由Javac编译生成()方法,初始化阶段就是执行该方法的过程。如果一个类中没有对变量的赋值也没有静态代码块,则编译器可以不为这个类生成()方法,接口不能有静态代码块,但是没有变量赋值,也是不会有()方法。接口与类的不同是,只有父接口定义的变量被使用时,父接口才会被初始化。Java虚拟机在执行一个类的()方法在多线程下是安全的,只有一个线程会去执行这个类的方法。

class DeadLockClass{
    static{
        if(true){
            System.out.println(Thread.currentThread().getName() + "init DeadLockClass ");
            while(true){
                
            }
        }
    }
    public static void main(String[] args){
        Runnable script = new Runnable(){
            public void run(){
                System.out.println(Thread.currentThread().getName() + " start");
                DeadLockClass dlc = new DeadLockClass();
                System.out.println(Thread.currentThread().getName() + " end");
            }
        };
        Thread t1 = new Thread(script);
        Thread t2 = new Thread(script);
        t1.start();
        t2.start();
    }
}

发生类初始化的情况
  1. 用new创建一个对象、反射创建对象
  2. 读取或者设置一个类型的静态字段(被final修饰的静态字段不算)
  3. 调用一个类型的静态方法
  4. 使用java.lang.reflect包的方法对类型进行放射调用(当调用时才会触发,如获取属性值,执行方法)
  5. 虚拟机启动main方法所在的类
  6. 子类进行初始化,父类还没有被初始化
  7. Class.forName
不会发生类初始化的情况
  1. 通过子类访问父类的静态域,不会初始化子类
  2. 通过数组定义类的应用(Myuser[] users = new MyUser[10]😉
  3. 对常量的引用

JVM内存模型

JVM的内存模型是指Java虚拟机在运行Java程序时所使用的内存模型

在这里插入图片描述

程序计数器

程序计数器是一块较小的内存空间,它用于指示当前线程所执行的字节码指令的地址。在多线程的情况下,每个线程都拥有自己的程序计数器,用于存储当前线程的执行地址。

Java虚拟机栈

Java虚拟机栈是线程私有的,用于存储Java方法执行的栈帧。每个栈帧包含了局部变量表、操作数栈、动态链接、返回地址等信息,用于支持Java方法的调用和执行。

内存区域有两种异常:

  1. 线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
  2. 如果Java虚拟机允许栈容量可以动态扩展,当栈的扩展无法申请足够的内存会抛出OutOfMemoryError异常
Java堆

Java堆是Java虚拟机所管理的最大的一块内存空间,用于存储Java对象和数组。Java堆可以分为新生代和老年代两部分,其中新生代又分为Eden区和两个Survivor区。

方法区

方法区用于存储类的元数据信息,包括类的名称、方法、字段等信息。方法区可以用于实现动态代理、反射等功能。

本地方法栈

本地方法栈与Java虚拟机栈类似,但是它用于存储本地方法的执行栈帧。

JVM的沙箱安全机制

JVM的沙箱安全机制是指在Java程序运行时,Java虚拟机会限制程序的执行权限,防止恶意代码的执行,从而保证Java程序的安全性。Java的沙箱安全机制主要体现在以下几个方面

  1. 类加载机制:Java的类加载机制采用双亲委派模型,可以避免同名类的重复加载,同时也可以防止恶意代码的执行。
  2. 安全管理器:Java虚拟机提供了一个安全管理器(Security Manager),可以控制程序对系统资源的访问权限,例如文件访问、网络访问、系统属性、进程控制等等。
  3. 字节码校验:Java虚拟机会对加载的字节码文件进行校验,防止字节码被恶意篡改,从而保证Java程序的安全性。
  4. 沙箱环境:Java虚拟机提供了一个沙箱环境(Sandbox),可以限制程序对系统资源的访问权限。沙箱环境是由安全管理器控制的,通过对程序的访问权限进行控制,可以避免程序对系统资源的滥用。

JVM的调优和监控

Java内存溢出

1.模拟Java堆内存溢出

// VM 参数 -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
public static void main(String[] args) {
	List<Object> list = new ArrayList<>();

	while (true){
		list.add(new Object());
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

D:\dev\spring_data_jpa\target\test-classes\java_pid7048.hprof

D:\dev\spring_data_jpa\java_pid6452.hprof IDEA启动生存

在这里插入图片描述

2.模拟栈内存溢出

Java虚拟机规范描述的异常:

  1. 如果线程请求的栈深度大于虚拟机所允许的栈深度,则抛出StackOverflowError。
  2. 如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError。

HotSpot虚拟机不支持栈的动态扩展,但是再创建线程申请内存时就因无法获取足够的内存而出现的异常,会是OutOfMemoryError异常。

设置虚拟机容量-Xss256k

public class StackOverTest01 {
    
    private int length = 0;
    
    private void stack(){
        length++;
        stack();
    }

    public static void main(String[] args) {
        StackOverTest01 obj = new StackOverTest01();
        try {
            obj.stack();
        }catch (Throwable e){
            System.out.println("stackLength: " + obj.length);
        }
    }
}

在这里插入图片描述

public class StackOverTest02 {

    static class InnerClass{

        public int length = 0;
        public void stack(){
            Map<String,String> map1 = new HashMap<>(1024);
            Map<String,String> map2 = new HashMap<>(1024);
            Map<String,String> map3 = new HashMap<>(1024);
            Map<String,String> map4 = new HashMap<>(1024);
            Map<String,String> map5 = new HashMap<>(1024);
            Map<String,String> map6 = new HashMap<>(1024);
            Map<String,String> map7 = new HashMap<>(1024);
            Map<String,String> map8 = new HashMap<>(1024);
            Map<String,String> map9 = new HashMap<>(1024);
            Map<String,String> map10 = new HashMap<>(1024);
            Map<String,String> map11 = new HashMap<>(1024);
            Map<String,String> map12 = new HashMap<>(1024);
            Map<String,String> map13 = new HashMap<>(1024);
            Map<String,String> map14 = new HashMap<>(1024);
            Map<String,String> map15 = new HashMap<>(1024);
            Map<String,String> map16 = new HashMap<>(1024);
            Map<String,String> map17 = new HashMap<>(1024);
            Map<String,String> map18 = new HashMap<>(1024);
            Map<String,String> map19 = new HashMap<>(1024);
            Map<String,String> map20 = new HashMap<>(1024);
            Map<String,String> map21 = new HashMap<>(1024);
            Map<String,String> map22 = new HashMap<>(1024);
            Map<String,String> map23 = new HashMap<>(1024);
            Map<String,String> map24 = new HashMap<>(1024);
            Map<String,String> map25 = new HashMap<>(1024);
            Map<String,String> map26 = new HashMap<>(1024);
            Map<String,String> map27 = new HashMap<>(1024);
            Map<String,String> map28 = new HashMap<>(1024);
            Map<String,String> map29 = new HashMap<>(1024);
            Map<String,String> map30 = new HashMap<>(1024);

            length++;

            stack();

        }

    }

    public static void main(String[] args) {
        InnerClass innerClass = new InnerClass();
        try {
            innerClass.stack();
        }catch (Throwable e){
            System.out.println("stackLength: " + innerClass.length);
        }
    }

}

在这里插入图片描述

模拟创建线程内存不足,引发的OutOfMemoryError,启动-Xss2m,给线程分配2m内存

由于本地内存太大,很难达到内存的最大值,把内存耗尽,通过在2核4G的服务器上面测试,达到了效果。

public class StackOverTest03 {

    private static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) {
        while (true){
            Thread thread = new Thread(() -> {

                count.incrementAndGet();

                int i = 0;

                while (true) {
                    if (i == 0){
                        if (count.get() % 10240 == 0){
                            System.out.println(Thread.currentThread().getName() + ": " + count);
                        }
                    }
                    try {
                        Thread.sleep(6000000);
                        i++;
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            thread.start();
        }
    }

}

在这里插入图片描述

3.模拟方法区和常量池内存溢出

由于JDK1.8之后,常量池是在堆内存中的,在设置永久代的大小时,程序结束也提示了,1.8不支持这个设置了。不加堆内存限制应该很难到达OutOfMemoryError。

public class PermGenTest01 {
    public static void main(String[] args) {
        // -XX:PermSize=6m -XX:MaxPermSize=6m -Xms20m -Xmx20m
        List<String> list = new ArrayList<>();
        int i = 0;
        while (true){
            list.add(String.valueOf(i++).intern());
        }
    }
}

在这里插入图片描述

JDK1.8之前,方法区内存也叫永久代,但是JDK1.8开始,去除了永久代,改为元空间

public class MethodAreaTest01 {

    static class InnerClass{}

    // -XX:MaxMetaspaceSize=10M 元空间最大值
    // -XX:MetaspaceSize=1M 元空间初始空间大小,到达该值会触发垃圾回收
    // -XX:MinMetaspaceFreeRatio= 垃圾回收之后控制最小的元空间剩余容量的百分比
    // -XX:PermSize=10M -XX:MaxPermSize=10m -XX:MaxMetaspaceSize=10M
    public static void main(String[] args) {
        while (true){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(InnerClass.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invoke(o,args);
                }
            });
            enhancer.create();
        }
    }
}

在这里插入图片描述

4.本机直接内存溢出

public class DirectMemoryTest01 {
    // -XX:MaxDirectMemorySize直接内存的最大容量,默认和java堆的最大值
    // -Xmx20M -XX:MaxDirectMemorySize=10M
    public static void main(String[] args) throws IllegalAccessException {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true){
            unsafe.allocateMemory(1024*1024);
        }
    }
}

在这里插入图片描述

垃圾收集器和内存分配

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【驾校管理系统源码】基于Springboot+Vue个人驾校预约管理系统

&#x1f345; 简介&#xff1a;500精品计算机源码学习 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 文末获取源码 目录 一、以下学习内容欢迎领取&#xff1a; Eclipse运行教学&#xff1a; Idea运行项目教学&#xff1a; Pycharm调试项目教学&#…

用Python手把手教你实现一个爬虫(含前端界面)

目录 前言爬虫基本原理使用Python的requests库发送HTTP请求使用BeautifulSoup库解析HTML页面使用PyQt5构建前端界面实现一个完整的爬虫程序结语 前言 随着互联网的飞速发展&#xff0c;再加上科技圈的技术翻天覆地的革新&#xff0c;互联网上每天都会产生海量的数据&#xff…

数据库更换版本

目录 0.前言 1.官网下载MySQL 2.配置初始化文件my.ini 3.初始化MySQL 4.安装mysql服务并启动修改密码 5.配置环境变量​编辑 0.前言 心累&#xff0c;为了完成实验&#xff0c;必须使用8.0版本导致我更新版本的时候&#xff0c;把sqlyog干崩溃了&#xff0c;什么版本不兼…

分清社保、医保、新农合

社保中的大头是养老保险&#xff0c;从上图可知成都每个月最低849.2元&#xff0c;对于底层人民来说价格不菲&#xff0c;但对应的医保才107元&#xff0c;那么能不能只交医保呢&#xff1f; 分三种情况&#xff1a; 1、如果我们购买的是城镇职工医疗保险&#xff0c;公司买的也…

<JavaEE> 单例模式的两种实现:“饿汉模式”和“懒汉模式”

目录 一、单例模式概述 二、“饿汉模式”实现单例模式 三、“懒汉模式”实现单例模式 3.1 单线程下的“懒汉模式” 3.2 多线程下的“懒汉模式” 一、单例模式概述 1&#xff09;什么是单例模式&#xff1f; 单例模式是一种设计模式。 单例模式可以保证某个类在程序中只存…

电源自动测试系统| 电源模块温度循环怎么测试?

在一些应用领域&#xff0c;电源模块会在极端环境温度条件下工作。为了确保电源在高低温环境下可以正常运行&#xff0c;满足设备需求&#xff0c;需要对电源模块进行温度循环测试。 温度循环测试是指电源模块经过升温、保温、降温等多次循环试验来检测其在温度变化下的耐热性、…

解决在Linux中进行redis的主从复制时出现的从机可以获取到主机的信息,主机获取不到从机的信息~

主机&#xff1a; 从机1&#xff1a; 从机2&#xff1a; 出现上述的原因是我在redis.conf中设置了密码&#xff0c;那么就导致了我在进行主从复制时&#xff0c;需要进行密码验证&#xff0c;然后我在网上查阅了很多资料&#xff0c;有的说让在从机中指定密码&#xff0c;有的说…

HarmonyOS开发上手

首先献出开发官网地址 &#xff08;https://developer.harmonyos.com/cn/develop/&#xff09; 本文内容 基础入门内容介绍安装DevEco StudioDevEco Studio常用功能介绍项目工程结构详解 1. 基础入门内容介绍 应用开发流程 在正式开始之前还需要了解一些有关的基础概念 方舟…

出现数据库出现没有时间格式的错误,实体类Date类型不对导致时间报错

目录 报错现场解决办法java与mysql中的日期类型及二者的对应关系和使用场景 报错现场 数据库最早时间为2023年1月1日&#xff0c;前端查询后却出现2022年12月31日的数据 数据库时间类型为date swagger接口测试 解决办法 讲until的Date改成sql类的Date&#xff0c;就可以了…

茄子科技张韶全:跨多云大数据平台DataCake在OceanBase的实践

11 月 16 日&#xff0c;OceanBase 在北京顺利举办 2023 年度发布会&#xff0c;正式宣布&#xff1a;将持续践行“一体化”产品战略&#xff0c;为关键业务负载打造一体化数据库。其中&#xff0c;在“数字化转型升级实践专场”&#xff0c;我们有幸邀请到了茄子科技大数据技术…

MYSQL练题笔记-聚合函数-各赛事的用户注册率

一、题目相关内容 1&#xff09;相关的表 2&#xff09;题目 3&#xff09;帮助理解题目的示例&#xff0c;提供返回结果的格式 二、自己初步的理解 有两张不同左右的表&#xff0c;用户表和赛事注册表。然后解题。 1.各种赛事的用户注册百分率 各种赛事的意味着通过contes…

ES6 import

这里 import 的文件是项目内自己 export 的对象&#xff0c;并非 package.json 里引用的包。 后者的打包策略和配置有关。 原理&#xff1a;彻底理解JavaScript ES6中的import和export - 知乎

深度学习(五):pytorch迁移学习之resnet50

1.迁移学习 迁移学习是一种机器学习方法&#xff0c;它通过将已经在一个任务上学习到的知识应用到另一个相关任务上&#xff0c;来改善模型的性能。迁移学习可以解决数据不足或标注困难的问题&#xff0c;同时可以加快模型的训练速度。 迁移学习的核心思想是将源领域的知识迁…

YOLOv8改进有效涨点 | 2023 | SPD-Conv空间深度转换卷积(高效空间编码技术)

一、本文介绍 本文给大家带来的改进内容是SPD-Conv&#xff08;空间深度转换卷积&#xff09;技术。SPD-Conv是一种创新的空间编码技术&#xff0c;它通过更有效地处理图像数据来改善深度学习模型的表现。SPD-Conv的基本概念&#xff1a;它是一种将图像空间信息转换为深度信息…

Leetcode每日一题学习训练——Python版(从二叉搜索树到更大和树)

版本说明 当前版本号[20231204]。 版本修改说明20231204初版 目录 文章目录 版本说明目录从二叉搜索树到更大和树理解题目代码思路参考代码 原题可以点击此 1038. 从二叉搜索树到更大和树 前去练习。 从二叉搜索树到更大和树 给定一个二叉搜索树 root (BST)&#xff0c;请…

【React设计】React企业级设计模式

Image Source : https://bugfender.com React是一个强大的JavaScript库&#xff0c;用于构建用户界面。其基于组件的体系结构和构建可重用组件的能力使其成为许多企业级应用程序的首选。然而&#xff0c;随着应用程序的规模和复杂性的增长&#xff0c;维护和扩展变得更加困难。…

FCRP第二题

【题目要求】 数据库中有一张地区数据统计表&#xff0c;但是并不规则 &#xff0c;记录类似于&#xff0c;225100:02:3:20160725是一串代码&#xff0c;以&#xff1a;分割&#xff0c;第1位为地区代码&#xff0c;第2位为分类代码&#xff0c;第3位为数量&#xff0c;第4位为…

Linux删除了大文件为什么磁盘空间没有释放?

某天&#xff0c;收到监控系统的告警信息&#xff0c;说磁盘空间占用过高&#xff0c;登上服务器&#xff0c;使用 df -h 一看&#xff0c;发现磁盘占用率已经 96%了&#xff1a; 通过查看 /usr/local/nginx/conf/vhost/xxx.conf 找到 access_log 和 error_log 的路径&#x…

在Python中探索图像相似性方法

在一个充斥着图像的世界里&#xff0c;衡量和量化图像之间相似性的能力已经成为一项关键任务。无论是用于图像检索、内容推荐还是视觉搜索&#xff0c;图像相似性方法在现代应用中起着至关重要的作用。 幸运的是&#xff0c;Python提供了大量工具和库&#xff0c;使得开发人员和…

【深度学习】Stable Diffusion中的Hires. fix是什么?Hires. fix原理

文章目录 **Hires. fix****Extra noise**Upscalers Hires. fix https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#hires-fix 提供了一个方便的选项&#xff0c;可以部分地以较低分辨率呈现图像&#xff0c;然后将其放大&#xff0c;最后在高分辨率下添…