JVM内存模型详解

2023-11-04

目录

1.JVM整体架构

2.JVM运行时内存

        2.1.PC程序计数器

        2.2.虚拟机栈

                2.2.1.什么是栈帧 

                2.2.2.局部变量表

                2.2.3.操作数栈

                2.2.4.动态链接

                2.2.5.方法返回地址

        2.3.本地方法栈

        2.4.堆

                 2.4.1.堆的概念

                 2.4.2.年轻代和老年代

                 2.4.3.对象分配过程

                 2.4.4.堆GC

        2.5.元空间

        2.6.方法区

        2.6.1.方法区内部结构

        2.7.运行时常量池

        2.8.直接内存


1.JVM整体架构

根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。

jvm内存模型
jvm内存模型
名称 特征 作用 配置参数 异常
程序计数器 占用内存小,线程私有,生命周期与线程相同 存储字节码运行号
虚拟机栈 线程私有,生命周期与线程相同,使用连续的内存空间 Java 方法执行的内存模型,存储局部变量表、操作栈、动态链接、方法出口等信息 -Xss StackOverflowError OutOfMemoryError
线程共享,生命周期与虚拟机相同,可以不使用连续的内存地址 保存对象实例,所有对象实例(包括数组)都要在堆上分配

-Xms

-Xsx

-Xmn

OutOfMemoryError
方法区 线程共享,生命周期与虚拟机相同,可以不使用连续的内存地址 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

-XX:PermSize:16M

-XX:MaxPermSize64M

-XX:MetaspaceSize=16M

-XX:MaxMetaspaceSize=64M

OutOfMemoryError
本地方法栈 线程私有 虚拟机使用到的Native方法服务 StackOverflowError OutOfMemoryError

 JVM分为五大模块: 类装载器子系统 、 运行时数据区 、 执行引擎 、 本地方法接口  垃圾收集模块 。

jvm内存架构图
jvm内存架构图

2.JVM运行时内存

        Java 虚拟机有自动内存管理机制,如果出现面的问题,排查错误就必须要了解虚拟机是怎样使用内存的。

Java7和Java8内存结构的不同主要体现在方法区的实现

        方法区是java虚拟机规范中定义的一种概念上的区域,不同的厂商可以对虚拟机进行不同的实现。

        通常使用的Java SE都是由Sun JDK和OpenJDK所提供。而该版本使用的VM就是 HotSpot VM。通常情况下,我们所用的java虚拟机指的就是HotSpot的版本。

JDK7 内存结构

jvm内存模型
jvm1.7内存模型

JDK8 内存结构

jvm内存模型
jvm1.8内存模型

针对JDK8虚拟机内存详解

jvm内存模型
jvm内存模型

JDK7和JDK8变化小结

jvm1.7与1.8对比
jvm1.7与1.8对比

线程私有的:

        程序计数器

        虚拟机栈

        本地方法栈

线程共享的:

        堆

        方法区

        直接内存(非运行时数据区的一部分)

对于Java8,HotSpots取消了永久代,那么是不是就没有方法区了呢?

        方法区只是一个规范,只不过它的实现变了。

        在Java8中,元空间(Metaspace)登上舞台,方法区存在于元空间(Metaspace)。同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。

方法区Java8之后的变化

  • 移除了 PermGen(永久代),替换为 Metaspace(元空间)
  • 永久代中的 class metadata(类元信息)转移到了 native memory(本地内存,而不是虚拟机)
  • 永久代中的 interned Strings(字符串常量池)和 class static variables(类静态变量)转移到了Java heap
  • 永久代参数 (PermSize MaxPermSize) -> 元空间参数 (MetaspaceSize MaxMetaspaceSize)

Java8为什么要将永久代替换成Metaspace?

  • 字符串存在永久代中,容易出现性能问题和内存溢出。
  • 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
  • Oracle 可能会将 HotSpot 与 JRockit 合二为一,JRockit没有所谓的永久代。

        2.1.PC程序计数器

        PC寄存器,是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令、分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

程序计数器的特点 

  1. 区别于计算机硬件的pc寄存器,两者不略有不同。计算机用pc寄存器来存放“伪指令”或地址,而相对于虚拟机,pc寄存器它表现为一块内存,虚拟机的pc寄存器的功能也是存放伪指令,更确切的说存放的是将要执行指令的地址。
  2. 当虚拟机正在执行的方法是一个本地(native)方法的时候,jvm的pc寄存器存储的值是undefined。
  3. 程序计数器是线程私有的,它的生命周期与线程相同,每个线程都有一个。
  4. 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

        Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器只会执行一条线程中的指令。

        因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。

        2.2.虚拟机栈

        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"); 
    }
    
}
jvm虚拟机栈
jvm虚拟机栈

                2.2.1.什么是栈帧 

        栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构。栈帧存储了方法的局部变量表、操作数栈、动态连接方法返回地址等信息。每一个方法从调用至执行完成的过程,都对应着一个栈帧在虚拟机栈里从入栈到出栈的过程。

jvm虚拟机栈
jvm虚拟机栈
jvm虚拟机栈
jvm虚拟机栈

                2.2.2.局部变量表

        局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。包括8种基本数据类型、对象引用(reference类型)和returnAddress类型(指向一条字节码指令的地址)。 其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。

                2.2.3.操作数栈

        操作数栈(Operand Stack)也称作操作栈,是一个后入先出栈(LIFO)。随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。

                2.2.4.动态链接

        Java虚拟机栈中,每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用,持有这个引用的目的是为了支持方法调用过程中的动态链接(Dynamic Linking)。

        动态链接的作用:将符号引用转换成直接引用。

                2.2.5.方法返回地址

        方法返回地址存放调用该方法的PC寄存器的值。一个方法的结束,有两种方式:正常地执行完成,出现未处理的异常非正常的退出。无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的PC计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息。 无论方法是否正常完成,都需要返回到方法被调用的位置,程序才能继续进行。

        2.3.本地方法栈

        本地方法栈(Native Method Stacks) 与虚拟机栈所发挥的作用是非常相似的, 其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务, 而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。

特点

  1. 本地方法栈加载native的但是方法, native类方法存在的意义当然是填补java代码不方便实现的缺陷而提出的。
  2. 虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
  3. 是线程私有的,它的生命周期与线程相同,每个线程都有一个。 

        在Java虚拟机规范中,对本地方法栈这块区域,与Java虚拟机栈一样,规定了两种类型的异常:

        (1) StackOverFlowError:线程请求的栈深度 > 所允许的深度。

        (2) OutOfMemoryError:本地方法栈扩展时无法申请到足够的内存。

        2.4.堆

                 2.4.1.堆的概念

        对于Java应用程序来说,Java堆(Java Heap)是虚拟机所管理的内存中最大的一块。 Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例, Java 世界里“几乎”所有的对象实例都在这里分配内存。“几乎”是指从实现角度来看, 随着Java语言的发展,现在已经能看到些许迹象表明日后可能出现值类型的支持, 即使只考虑现在, 由于即时编译技术的进步, 尤其是逃逸分析技术的日渐强大, 栈上分配、标量替换优化手段已经导致一些微妙的变化悄然发生, 所以说Java对象实例都分配在堆上也渐渐变得不是那么绝对了。

jvm内存模型
jvm内存模型

堆的特点

(1) 是Java虚拟机所管理的内存中最大的一块。

(2) 堆是jvm所有线程共享的。 (堆中也包含私有的线程缓冲区 Thread Local Allocation Buffer )

(3) 在虚拟机启动的时候创建。

(4) 唯一目的就是存放对象实例,几乎所有的对象实例以及数组都要在这里分配内存。

(5) Java堆是垃圾收集器管理的主要区域。

(6) 很多时候java堆也被称为“GC堆”(Garbage Collected Heap)。从内存回收的角度来看,现在收集器基本都采用分代收集算法,所以Java堆可以细分为:新生代和老年代;新生代又可以分为:Eden 空间、From Survivor空间、To Survivor空间。

(7) java堆计算机物理存储上不连续、逻辑上连续,也是大小可调节的(通过-Xms和-Xmx控制)。

(8) 方法结束后,堆中对象不会马上移出仅仅在垃圾回收的时候时候才移除。

(9) 如果堆中没有内存完成实例的分配,且堆也无法再扩展时,将会抛出 OutOfMemoryError 异常

堆的分类

现在垃圾回收器都使用分代理论,堆空间也分类如下:

在Java7 Hotspot虚拟机中将Java堆内存分为3个部分:

  • 青年代 Young Generation
  • 老年代 Old Generation
  • 永久代 Permanent Generation
jvm堆
jvm堆

在Java8以后,由于方法区的内存不在分配在Java堆上,而是存储于本地内存元空间Metaspace中,所以永久代就不存在了。

jvm堆
jvm堆

                 2.4.2.年轻代和老年代

JVM中存储java对象可以被分为两类:

1)年轻代(Young Gen):年轻代主要存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。年轻代分成 1个Eden Space和 2个Suvivor Space(from 和 to)。

2)年老代(Tenured Gen):年老代主要存放JVM认为生命周期比较长的对象(经过几次的Young Gen的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁。 

新生代和老年代堆结构占比

jvm堆比例
jvm堆比例

        从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。

        默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生 代 ( Young ) = 1/3 的堆空间大小老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to 以示区分。 默认的,Eden : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域 是空闲着的。因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间

                 2.4.3.对象分配过程

        JVM设计者不仅需要考虑到内存如何分配,在哪里分配等问题,并且由于内存分配算法与内存回收算法密切相关, 因此还需考虑GC执行完内存回收后是否存在内存碎片。

分配过程

1.new 的对象先放在 Eden区。该区域有大小限制

2.当 Eden区 填满时,程序又需要创建对象,JVM的垃圾回收器将对Eden区进行垃圾回收(Minor GC),将 Eden区 中不再被其他对象引用的额对象进行销毁,再加载新的对象放到 Eden区

3.然后将 Eden区 中的剩余对象移动到 S0区

4.再次触发垃圾回收时,上次幸存下来的放在 S0区 的对象,如果没有被回收,就会放到S1区

5.如果再次经历垃圾回收,存货对象会重新返回 S0区,接着再去S1区。

6.累计次数到达默认的15次,这会进入 old 区。 可通过调整阈值 -XX:MaxTenuringThreshold=N 改变累计次数

7.old 区 内存不足时,会再次出发GC:Major GC 进行 old区 的内存清理

8.如果 old区 执行了 Major GC 后仍然没有办法进行对象的保存,就会报OOM异常

jvm GC
jvm GC
jvm GC
jvm GC

分配对象的流程: 

jvm 对象创建流程
jvm 对象创建流程

                 2.4.4.堆GC

        Java 中的堆也是 GC 收集垃圾的主要区域。GC 分为两种:一种是部分收集器(Partial GC)另一类是整堆收集器 (Full GC)

部分收集器: 不是完整收集java堆的的收集器,它又分为:

  • 新生代收集(Minor GC/Young GC): 新生代的垃圾收集
  • 老年代收集(Major GC/Old GC): 老年代的垃圾收集 (CMS GC 单独回收老年代)
  • 混合收集(Mixed GC): 收集整个新生代及老年代的垃圾 (G1 GC会混合回收, region区域回收) 

整堆收集(Full GC): 收集整个java堆和方法区的垃圾收集器

年轻代GC触发机制:

  • 年轻代空间不足,就会触发Minor GC, 这里年轻代指的是Eden区满
  • Minor GC会引发 STW(stop the world) ,暂停其他用户的线程,等垃圾回收接收,用户的线程才恢复

老年代GC (Major GC)触发机制:

  • 老年代空间不足时,会尝试触发MinorGC. 如果空间还是不足,则触发Major GC
  • 如果Major GC , 内存仍然不足,则报错OOM
  • Major GC的速度比Minor GC慢10倍以上.

FullGC 触发机制:

  • 调用System.gc() , 系统会执行Full GC ,不是立即执行
  • 老年代空间不足
  • 方法区空间不足
  • 通过Minor GC进入老年代平均大小大于老年代可用内存

GC调优命令参考https://blog.csdn.net/qq_42029989/article/details/126271506 

        2.5.元空间

        在JDK1.7之前,HotSpot 虚拟机把方法区当成永久代来进行垃圾回收。而从 JDK 1.8 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。

HotSpots取消了永久代,那么是不是也就没有方法区了呢?

        当然不是,方法区是一个规范,规范没变,它就一直在,只不过取代永久代的是元空间(Metaspace)而已。

Metaspace和永久代有什么不同的?

  • 存储位置不同:永久代在物理上是堆的一部分,和新生代、老年代的地址是连续的,而元空间属于本地内存。
  • 存储内容不同:在原来的永久代划分中,永久代用来存放类的元数据信息、静态变量以及常量池等。现在类的元信息存储在元空间中,静态变量和常量池等并入堆中,相当于原来的永久代中的数据,被元空间和堆内存给瓜分了。

为什么要废弃永久代,引入元空间?

  • 在原来的永久代划分中,永久代需要存放类的元数据、静态变量和常量等。它的大小不容易确定,因为这其中有很多影响因素,比如类的总数,常量池的大小和方法数量等,-XX:MaxPermSize 指定太小很容易造成永久代内存溢出。
  • 移除永久代是为融合HotSpot VM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代永久代会为GC带来不必要的复杂度,并且回收效率偏低。

废除永久代的好处

  • 由于类的元数据分配在本地内存中,元空间的最大可分配空间就是系统可用内存空间。不会遇到永久代存在时的内存溢出错误。
  • 将运行时常量池从PermGen分离出来,与类的元数据分开,提升类元数据的独立性。
  • 将元数据从PermGen剥离出来到Metaspace,可以提升对元数据的管理同时提升GC效率。

        2.6.方法区

方法区(Method Area) 与Java堆一样, 是各个线程共享的内存区域, 它用于存储已被虚拟机加载的类型信息、 常量、 静态变量、 即时编译器编译后的代码缓存等数据

《Java虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但些简单的实现可能不会选择去进行垃圾收集或者进行压缩”。对HotSpot而言,方法区还有一个别名叫做Non-Heap(非堆),就是要和堆分开。

        元空间、永久代是方法区具体的落地实现。方法区看作是一块独立于Java堆的内存空间,它主要是用来存储所加载的类信息的

创建对象各数据区域的声明:

方法区的特点:

  • 方法区与堆一样是各个线程共享的内存区域
  • 方法区在JVM启动的时候就会被创建并且它实例的物理内存空间和Java堆一样都可以不连续
  • 方法区的大小跟堆空间一样 可以选择固定大小或者动态变化
  • 方法区的对象决定了系统可以保存多少个类,如果系统定义了太多的类 导致方法区溢出虚拟机同样会抛出 (OOM)异常(Java7之前是 PermGen Space (永久代) Java 8之后 是MetaSpace(元空间))
  • 关闭JVM就会释放这个区域的内存

        2.6.1.方法区内部结构

jvm 方法区
jvm 方法区

类加载器将Class文件加载到内存之后,将类的信息存储到方法区中。

方法区中存储的内容:

  • 类型信息(域信息、方法信息)
  • 运行时常量池
jvm 方法区
jvm 方法区

类型信息

对每个加载的类型(类Class、接口 interface、枚举enum、注解 annotation),JVM必须在方法区中存储以下类型信息:

  1. 这个类型的完整有效名称(全名 = 包名.类名)
  2. 这个类型直接父类的完整有效名(对于 interface或是java.lang. Object,都没有父类)
  3. 这个类型的修饰符( public, abstract,final的某个子集)
  4. 这个类型直接接口的一个有序列表

域信息

域信息,即类的属性,成员变量,JVM必须在方法区中保存类所有的成员变量相关信息及声明顺序。

域的相关信息包括:域名称、域类型、域修饰符(pυblic、private、protected、static、final、volatile、transient的某个子集)

方法信息

JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:

  1. 方法名称方法的返回类型(或void)
  2. 方法参数的数量和类型(按顺序)
  3. 方法的修饰符public、private、protected、static、final、synchronized、native,、abstract的一个子集
  4. 方法的字节码bytecodes、操作数栈、局部变量表及大小( abstract和native方法除外)
  5. 异常表(abstract和 native方法除外)。每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏 移地址、被捕获的异常类的常量池索引

        2.7.运行时常量池

常量池与运行时常量池的区别

常量池:存放编译期间生成的各种字面量与符号引用

运行时常量池:常量池表在运行时的表现形式,编译后的字节码文件中包含了类型信息、域信息、方法信息等。通过ClassLoader将字节码文件的常量池中的信息加载到内存中,存储在了方法区的运行时常量池中。

        字节码中的常量池 Constant pool 只是文件信息,它想要执行就必须加载到内存中。而Java程序是靠 JVM,更具体的来说是JVM的执行引擎来解释执行的。执行引擎在运行时常量池中取数据,被加载的字节码常量池中的信息是放到了方法区的运行时常量池中。

它们不是一个概念,存放的位置是不同的。一个在字节码文件中,一个在方法区中。

对字节码文件反编译之后,查看常量池相关信息: 

jvm 常量池
jvm 常量池

要弄清楚方法区的运行时常量池,需要理解清楚字节码中的常量池。

一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述信息外,还包含一项信息那就是常量池表( Constant pool table),包括各种字面量和对类型、域和方法的符号引用

常量池,可以看做是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型

常量池表Constant pool table: 

jvm 常量池
jvm 常量池

在方法中对常量池表的符号引用

jvm 常量池
jvm 常量池

为什么需要常量池?

举例来说:

public class Solution {
    public void method() {
        System.out.println("are you ok");
    }
}

这段代码很简单,但是里面却使用了 String、 System、 PrintStream及Object等结构。如果代码多,引用到的结构会更多!这里就需要常暈池,将这些引用转变为符号引用,具体用到时,采取加载。

        2.8.直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分。

在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区 (Buffer)的I/O方 式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的 DirectByteBuffer 对象作为这块内存的引用进行操作。 这样能在一些场景中显著提高性能, 因为避免了在Java堆和Native堆中来回复制数据。

jvm 直接内存
jvm 直接内存

NIO的Buffer提供一个可以直接访问系统物理内存的接口——DirectBuffer。

DirectByteBuffer继承自ByteBuffer,但和普通的ByteBuffer不同。普通的ByteBuffer仍在JVM堆上分配内存,其最大内存受到最大堆内存的限制。而DirectByteBuffer直接分配在物理内存中,并不占用堆空间。在访问普通的ByteBuffer时,系统总是会使用一个“内核缓冲区”进行操作。 而DirectByteBuffer所处的位置,就相当于这个“内核缓冲区”。因此,使用DirectByteBuffer是一种更加接近内存底层的方法, 所以它的速度比普通的ByteBuffer更快。

 通过使用堆外内存,可以带来以下好处:

  1. 改善堆过大时垃圾回收效率,减少停顿。Full GC时会扫描堆内存,回收效率和堆大小成正比。Native的内存,由OS负责管理和回收。
  2. 减少内存在Native堆和JVM堆拷贝过程,避免拷贝损耗,降低内存使用。
  3. 可突破JVM内存大小限制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM内存模型详解 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • 区块链学习笔记(四)——Proof of Work

    区块链学习笔记 四 Proof of Work 前言 一 PoW是什么 二 要点 1 比特币的构成 2 PoW的优缺点 三 为什么是乌托邦式的共识 前言 我们常说的共享机制有Pow PoS DPoS 而区块链采用的是谁获胜谁获奖的原则 即工
  • 遥感+python 1.5 重投影

    遥感 python 1 5 重投影 目录 遥感 python 1 5 重投影 一 重投影概念 二 代码实现 2 1 读取影像 2 2 输出影像 2 3 坐标转换 本章节 笔者主要讲述重投影的概念 原理 即代码实现 一 重投影概念 当考虑两幅
  • selector xmlns:android=“http://schemas.android.com/apk/res/android

  • Windows10 下安装mmdetection 问题之“cannot import name ‘deform_conv_cuda‘”

    最近在使用mmdetection工具箱 官方只给出Linux系统下的安装方法 自己尝试在Windows10下的安装 其中遇到过一些问题 在此记录下来 希望给小伙伴一些帮助 安装环境 VS2015 CUDA 9 0 Pytorch 1 1 t
  • centos系统ACFS-9459: ADVM/ACFS is not supported

    centos6 3系统发现acfs和advm无法使用 ASMCA图形界面的acfs和volume选项卡为灰色 这是由于acfs不支持centos系统导致的 Last login Thu Dec 14 09 33 10 2017 from 1
  • cuda Sample 功能分析(1-st 记) 0_Introduction 之 asyncAPI

    源码链接 https github com NVIDIA cuda samples blob v11 8 Samples 0 Introduction asyncAPI asyncAPI cu 首先 这个sample不是演示async co
  • C++:rand()函数和srand()函数解读

    1 srand unsigned int t 这个是设定种子 因为电脑取随机数是伪随机 只要种子一样 则取出来的数一定一样 这里用time 0 这个内函数 copy则是返回了当前的时间值 这个值是按照时间而变化的 所以 srand unsi
  • java中实现多态的机制是什么_java多态机制是什么

    java多态机制是什么 java中实现多态的机制是依靠父类或接口的引用指向子类 从而实现了一个对象多种形态的特性 其中父类的引用是在程序运行时动态的指向具体的实例 调用该引用的方法时 不是根据引用变量的类型中定义的方法来运行 而是根据具体的
  • 专治疑难系列 - 解决Ubuntu忘记root密码问题

    博客主页 Passerby Wang的博客 CSDN博客 系统运维 云计算 Linux基础领域博主 所属专栏 专治疑难系列 上期文章 专治疑难系列 解决win11中xbox开机自启问题 如觉得博主文章写的不错或对你有所帮助的话 还望大家多多
  • python多线程获取百度搜索(5.26更新)

    1 网站 输入搜索内容 获取搜索结果 进行保存 把内容整理后保存到mysql数据库 保存字段 关键字 标题 真实网址 简介 原网站名称 2 爬取结果 3 编写爬虫 爬虫使用scrapy框架编写 分布式 多线程 编写Items class B
  • Win10做系统,你自己就可以完成,不要再让别人帮你做系统啦(保姆级教学,手把手带你一步一步走!!!)你不会还不会做系统吧??快来看一看呀~

    我在这里把win10系统网址给大家放在这里啦 下载 Windows 10 microsoft com 然后下载下来之后 大家准备一个16G以上的空U盘 然后打开我们下载的这个文件 然后大家选择对应的U盘就可以啦 我的电脑是DELL 所以我就
  • 对于web代码基础了解

    快捷方式 1 基本骨架 shift 2 备注 ctrl 基本代码 1 段落标签 p p 2 换行标签 3 水平线标签 hr 4 加粗 strong strong 5 倾斜 em em 和 i i 6 容器 独占一行 div div 7 容器
  • Functions___CH_12

    12 1 Function Pointers Pointers to functions The syntax for creating a non const function pointer is one of the ugliest
  • 历时6个月, 非CS专业的我, 终于在毕业前拿到了谷歌软件工程师offer!

    本文作者 Isabel 本科就读于上海财经 研究生就读于CMU information management相关专业 在来Offer的帮助下成功 转码 入职谷歌 就在离毕业还有一个多月的时候 我收到了来自谷歌的offer 至此 心中的一块大
  • 机器视觉、目标检测常见应用场景

    机器视觉 目标检测常见应用场景 人脸人体检测 智能美肤 在保持皮肤质感的同时 自动对脸部进行匀肤 去瑕疵 痘 痘印 雀斑等 操作 并对全身皮肤进行美白 智能瘦脸 系统自动检测并分析人脸五官特征 生成脸部五官调整瘦脸后的图像 图像人脸融合 图
  • 华为OD机考题目(自动化测试)

    目次 1 求第k长的字串的长度 2 上N阶台阶问题 3 踢出石子问题 1 求第k长的字串的长度 描述 一个字符串只包含大写字母 求其连续相同字母子串中 长度第K长的子串长度 相同字母只取 最长那个子串 例 AAAAHHHBBCDHHHH K
  • SpringBoot集成Hutool 实现数据库数据导出到Excel 功能

    日常开发中 在B端页面上 经常需要将数据库中的数据 导出到Excel 我们今天用Hutool工具包 实现一下这个功能 一 Hutool简介 Hutool是一个功能丰富且易用的Java工具库 通过诸多实用工具类的使用 旨在帮助开发者快速 便捷
  • Lua UnPack函数用法

    这篇文章主要介绍了Lua UnPack函数用法实例 unpack它接受一个数组 table 作为参数 并默认从下标1开始返回数组的所有元素 local info 1 2 3 4 5 6 local a b c d e f unpack in
  • jenkins_svn_maven持续集成

    详解Jenkins svn maven 项目持续集成 第一步 由于刚刚接触jenkins 并不知道他是个什么东西 首先百度一下 然后进入官网 下载安装包 第二步 windows 安装 下载完了 打开里面有2个文件 setup exe Jen
  • JVM内存模型详解

    目录 1 JVM整体架构 2 JVM运行时内存 2 1 PC程序计数器 2 2 虚拟机栈 2 2 1 什么是栈帧 2 2 2 局部变量表 2 2 3 操作数栈 2 2 4 动态链接 2 2 5 方法返回地址 2 3 本地方法栈 2 4 堆