Java面试必备,JVM核心知识点总结!

2023-10-27

JVM基础

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

作用:记住下一条JVM指令

特点:

  • 线程私有
  • 唯一一个不会出现内存溢出的区域

虚拟机栈(Java virtual mechine Stack)

线程私有

  • 每个线程运行时所需要的内存
  • 每个栈由多个栈帧Frame组成,对应着每次方法调用时占的内存
  • 每个线程只能有一个当前活动栈帧,对应着当前正在执行的方法
三个问题

一、垃圾回收是否涉及栈内存?

不会:垃圾回收的是堆内存的无用数据,栈帧调用完会自动弹出栈,不需要垃圾回收。

二、栈内存分配越大越好?

不是,物理内存一定,栈内存分配越大,线程数就会越少,并且较大的栈内存并不会提升运行速度,只不过像递归调用可以存储更多栈帧。可通过以下虚拟机参数调节栈内存大小

三、方法内的局部变量是否线程安全?

  • 如果方法内局部变量没有逃离方法的作用访问,则线程安全
  • 如果局部变量引用了对象,并逃离了方法的作用访问(如返回对象变量,如对象作为参数传入方法)需要考虑线程安全问题

栈内存溢出

两种情况,会抛出java.lang.StackOverflowError的异常

栈帧过多(一般出现在递归)

栈帧过大,栈内存分配较小(一般不容易出现)

线程运行诊断

CPU占用过高,定位哪个线程引起的

  • Linux系统下top命令找出对应的进程PID
  • ps H -eo pid,tid.%CPU | grep 进程ID (用ps命令进一步定位哪个线程占用CPU过高)
  • jstack 进程id 列出当前Java进程下的所有的线程,根据十六进制线程id进行定位线程

程序很长时间没有获得结果(常见死锁问题)

  • jstack 进程id 列出当前Java进程下的所有的线程,根据十六进制线程id进行定位线程

本地方法栈

特点:线程私有

作用:Java代码不能很好的与操作系统打交道,因此采用native关键字,API调用C/C++代码,实现对操作系统相关API调用,这些方法(如Object类的notyAll,wait方法)运行需要单独的栈内存空间,称之为本地方法栈。

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

特点:

  • 线程共享,需要考虑线程安全问题
  • 有垃圾回收机制(堆中不在引用的对象)

堆内存溢出

会抛出异常OutOfMemoryError:Java heap space

调节堆空间内存大小 -Xmx内存大小

方法区(概念)

特点:线程共享

定义:存储包含类的结构相关一些信息(包含运行时常量池,类的成员变量,方法数据,成员方法构造器方法的代码部分)和类的加载器的信息,

方法区在虚拟机启动时被创建。

JDK1.6 与JDK 1.8 的对比

  • 1.8方法区的实现是元空间,占用的是操作系统的内存,并将常量池中的StringTable移到堆内存中。
  • 1.6方法区的实现是永久代,占用的是堆内存。

内存溢出

也会抛出异常OutOfMemoryError:Metaspace 1.8及以后,OutOfMemoryError:PermGen space 1.7及之前

调节方法区内存大小参数

-XX:MaxMetaspaceSize内存大小 JDK1.8及以后

-XX:MaxPermSize内存大小 JDK1.7及以前

出现场景
  • spring或mybatis都会用到cglib动态代理产生很多代理类,可能会出现OOM。

运行时常量池

常量池:就是一张表,虚拟机根据这张表找到需要的执行的类名,方法名,参数类型,字面量等信息

运行时常量池:位于*.class文件中,当类被加载,常量池信息就会加载到运行时常量池中,并将里面的符号转换成内存地址。

StringTable串池:

位于堆内存中, JDK1.6及以前位于常量池中,因为大量运用,老年代回收效率低,后续放在队中。

StringTable串池是延迟加载的,起初为空,用到才会转换新的String对象,且数组中对象不会重复转换【唯一】。

s1、s2是变量,引用的值可能改变,因此必须运行时进行StringBuilder拼接,返回一个新的对象

  • s1+“b”,s2+“a”,s1+s2都与"ab"不相等,原因是不同对象

此时"a"+"b"值固定,已经在编译期间进行优化完成,不需要运行时解析变量拼接。

public static void main(String[] args) {
    //串池对象【"a"】
    //堆对象【new String("a")】
    System.out.println(new String("a")=="a"); //false 说明串池与堆中对象不是同一个
}
public static void main(String[] args) {
    //串池【"a","b"】一旦出现"a"就会创建串池对象
    //堆池【ab,new String("a"),new String("b")】
    String ab =new String("a")+new String("b");
    String abi = ab.intern(); //尝试将ab变量String对象放入串池,并返回串池的对象名为abi
    //串池【"a","b","ab"】 因为串池中没有此"ab"值的常量对象,因此放入成功
    System.out.println(ab =="ab"); //true ab变量对象已在串池中
    System.out.println(abi =="ab"); //true abi变量引用返回的串池对象"ab"
}
public static void main(String[] args) {
    String x ="ab"; //将"ab"放入串池
    //串池【"a","b","ab"】一旦出现"a"就会创建串池对象
    //堆池【ab,new String("a",new String("b")】
    String ab =new String("a")+new String("b");
    String abi = ab.intern(); //尝试将ab变量String对象放入串池,并返回串池的对象"ab"
    //串池【"a","b","ab"】 因为串池中"ab"值的常量对象,因此放入失败
    System.out.println(ab =="ab"); //false 放入失败,ab变量对象不是串池对象
    System.out.println(abi =="ab"); //true abi变量引用指向返回的"ab"串池对象
}

上述代码最后一问补充:

//调换顺序后,结果为true,但如果是JDK1.6及以前都是false
x2.intern();
String x1 = "cd";
垃圾回收

当堆内存满时,会对串池中的常量进行垃圾回收,没有引用的常量会被回收!

设置堆内存为10m,打印串池和垃圾回收详细信息

-Xmx10m -XX:+PrintStringTableStatistics -XX:+PrintGCDetails -verbose:gc
性能调优
-XX:StringTableSize=20000(桶个数)

对于常量字符串特别多又重复(读取很多单词的文件)的情况下,intern()方法将字符串入池,适当将-XX:StringTableSize调大,减少hash冲突,增加执行速度。

检测工具

jps -------》 显示java进程id

jmap -heap 进程id -------》显示堆内存的详细信息

jvisualvm ,jconsole -------》图形化界面显示各线程详细信息

直接内存(Direct Memory)

  • 常见于NIO操作,用于数据缓冲区
  • 分配回收成本较高,但读写性能高
  • 不受JVM内存回收管理

直接内存在Java堆内存与系统内存中共享,减少了数据的一次复制。

内存溢出

抛出异常:Java.lang.OutOfMemoryError: Direct buffer memory

分配和回收管理

获取Unsafe对象需要通过反射

  • 直接内存使用底层Unsafe类管理(分配和释放等等)的,释放需要主动调用freeMemory 方法。
  • ByteBuffer 的实现内部,使用了Cleaner(虚引用)来监测ByteBuffer对象,一旦ByteBuffer对象被回收,那么就会由RefernceHandler线程通过 Cleaner 的 clean 方法调用 freeMemory来释放直接内存。
JVM参数

-XX:+DisableExplicitGC JVM参数禁用显式调用 System.gc() 垃圾回收,因为 System.gc() 是full GC 影响性能。

垃圾回收

如何判断一个垃圾可以回收

一、引用计数法

只要一个对象被一个变量引用,就让对象的计数加一,如果对象被引用两次,计数就变成2,如果某一个变量不在引用

这个对象了,就让计数减一,当对象引用计数等于0时,意味着是垃圾对象,等待垃圾回收。

问题:对象循环引用导致计数不会等于0,造成内存泄漏。

✳二、可达性分析算法 【Java虚拟机采用】

判定对象是否存活,扫描堆中对象先确定一系列的根对象GC Roots,判断每个对象是不是直接或间接的被根对象引

用,如果没有任何引用,证明对象是可回收的。

固定根对象 GC Roots

  • 虚拟机栈中引用的对象(参数,局部变量,临时变量等)
  • 静态属性引用的对象
  • 常量引用的对象(串池)
  • 本地方法栈的引用对象
  • 虚拟机内部的引用(基本数据类型对应的Class对象,异常对象)
  • 同步锁持有的对象(synchronized括号里的对象)
四种引用

强引用

只有强引用关系不存在时,即所有GC Root 都不通过强引用该对象,该对象才被垃圾回收。

Object obj = new Object(); //声明强引用
软引用

描述一些还有用,但非必须的对象,仅有软引用引用的对象,垃圾回收后,内存仍不足的情况下会回收。

  • 可配合引用队列来释放软引用自身
SoftReference<Object> sf = new SoftReference<>(new Object());//创建软引用
弱引用

描述非必须的对象,仅被弱引用引用的对象,垃圾回收时,无论内存是否充足,都会回收该对象。

  • 可配合引用队列来释放软引用自身
WeakReference<Object> wrf = new WeakReference<>(new Object());//创建弱引用
System.out.println(wrf.get()); // java.lang.Object@4b67cf4d
System.gc(); //执行gc
System.out.println(wrf.get()); //null
虚引用

必须配合引用队列释放自身,在创建时必须提供一个引用队列作为参数。主要配合ByteBuffer使用,被引用对象回收后,会将虚引用入队,由ReferenceHandler线程调用虚引用相关方法释放自身。

  • 它不能单独使用,也无法通过虚引用来获取被引用的对象。当试图通过虚引用的get()方法取得对象时,总是null。

  • 当垃圾回收器准备回收一个对象时,如果发现它还有虛引用,就会在回收对象后,将这个虚引用加入引用队列,以通知

    应用程序对象的回收情况。

ReferenceQueue<Object> phantomQueue = new ReferenceQueue<>(); //指定引用队列
PhantomReference<Object> prf = new PhantomReference<>(new Object(),phantomQueue);//创建弱引用
System.out.println(prf.get()); //null
终结引用
  • 它用于实现对象的finalize()方法,也可以称为终结器引用。
  • 无需手动编码,其内部配合引用队列使用。
  • 在GC时, 终结器引用入队。由Finalizer线程通过终结器引用找到被引用对象并调用它的finalize()方法,第二次GC时才能回收被引用对象。

垃圾回收算法

一、标记清除算法

特点:速度快

缺点:造成内存碎片

二、标记整理算法

特点:涉及内存地址的移动,速度慢

优点:不会造成内存碎布

三、复制算法

特点:没有内存碎片,速度最快

缺点:造成双倍内存空间的占用

分段理论

不同对象生命周期不一样,把Java堆分成新生代老年代,根据各个年代的特点,使用不同的三种垃圾回收算法的集合。

Stop the world

每一次垃圾回收会触发Stop the World 暂停一切用户线程,因为对象的迁移涉及内存地址的转换,避免出现混乱,垃圾回收完成后,用户线程恢复!

新生代

每次垃圾收集都会有大批对象死去,每次回收后存活的少量对象,会通过寿命+1来晋升,触发Stop the world。

垃圾回收:Minor GC 【标记+复制算法】

老年代

寿命=15的对象会迁移至老年代。寿命在对象头以4bit表示,最大值为15 ,触发Stop the world。

垃圾回收:Major GC 【标记+整理算法】

整体回收

Full GC 新生代和老年代一起进行垃圾回收,之后触发Stop the world。触发Stop the world

具体步骤

① 对象首先分配在伊甸园区,新生代内存不足时,会触发一次 Minor GC ,伴随着 Stop the World

② 伊甸园和From幸存区中存活的对象会Copy到To区中,并且交换From和To区域,其存活对象的寿命会加1.

③ 当寿命超过阈值时,会晋升到老年代区域。阈值最大是15,有些情况(新生代内存严重不足)会提前。

④ 当老年代内存空间不足时,先尝试触发Minor GC ,如果内存还不足,触发 Full GC,Stop the world 时间会更长。

垃圾回收JVM参数整理

大对象直接晋升老年代

新生代内存一定不够,老年代内存空间可以容纳的情况下

OOM

新生代和老年代的空间都不足以放入当前大对象,抛出OOM异常,不同线程抛出OOM不会影响其他线程的执行!

垃圾回收器

一、串行

Serial /SerialOld收集器

新生代采用 Serial 利用复制算法,效率高,老年代采用 SerialOld 标记整理算法。新生代+老年代回收两次STW。

用户线程在达到安全点时,其中一个线程抢占执行垃圾回收任务(还有stop the world),其他线程阻塞,完成之后恢复。

  • 单线程
  • 堆内存较小,适合个人电脑

二、吞吐量优先

Parallel Scavenge/ Parallel Old 收集器

新生代采用 Parallel Scavenge 利用复制算法,效率高,老年代使用 Parallel Old 多线程和 “标记-整理” 算法。新生代+老年代回收两次STW。

用户线程在达到安全点时,所有线程并行执行垃圾回收任务(还有stop the world),完成之后恢复

  • 多线程
  • 堆内存较大,多核CPU
  • 目的单位时间内,尽可能减少Stop the world 的时间

区别 1小时的单位时间

吞吐量优先:0.2+0.2(共执行2次)

响应时间优先:0.1+0.1+0.1+0.1+0.1(共执行5次)

垃圾回收线程个数与CPU核心数相同,执行垃圾回收线程时,CPU占用率会大幅提高。

三、响应时间优先

CMS收集器

基于标记清除算法,对于造成的内存碎片,采用基于标记整理算法的Serial Old回收器执行Full GC作为补偿。产生浮动

垃圾【并发清理其他用户线程产生的垃圾对象需下次清理】

适用场景

  • 多线程
  • 堆内存较大,多核CPU
  • 目的:尽可能让每次Stop the wordl 的时间减少

G1收集器

G1适合作为服务端垃圾收集器,应用在多处理器和大内存的条件下,可以实现高吞吐量的同时,尽可能满足垃圾收集

较短可控的暂停时间。

整体基于标记清除算法,局部采用复制算法。

垃圾收集器采用分区(不连续的Region),除了Full GC 外,还包含年轻代和部分老年代的Mixed GC,分为4阶段。

  • 初始标记 【标记根对象】

    伊甸园区域空间不足时,年龄较大的对象放入老年区,G1采用复制算法,触发Minor GC和STW,时间很短。【单一线程运行,其余阻塞】

  • 并发标记 【随着根对象的引用标记其他对象 SATB算法】

    老年代占用堆空间达到阈值时,进行并发标记,不会STW,【JVM参数可调阈值】。

  • 最终标记【并发标记中漏掉的对象】

    规定时间内,标记并发标记中新变化的回收价值高的区域

  • 筛选回收【复制标记存活的对象进入新的老年代区域,清除旧内存】

并发失败后,即老年代区域仍不够,就会进入多线程收集器执行Full GC!

应用

一般用于自定义类加载器(框架)会采用!

为避免Full GC,可控制老年代垃圾回收的阈值,JVM参数

-XX:initiatingHeapOccupancyPercent=45% 设置 【默认】

JDK 9 中设置后可进行自动的动态调整。

算法细节

卡表减少GC Root的搜寻时间

新生代回收需要寻找根对象,根对象有一部分是来自老年代的,老年代对象多,遍历直接搜对象效率太低,因此采用卡

表的数据结构将老年代细分更小的单位(卡),如果老年代中卡中存有根对象引用了新生代,标记为脏卡,通过写屏

障更新脏卡,避免找整个老年代。

多线程下增加写屏障保证重新标记阶段安全

当对象引用发生改变时,JVM会加入写屏障,只要对象引用发生改变,写屏障代码会执行,会将对象置为待处理的状

态,并放入队列,并发标记结束后再判断是否需要回收。

类加载

加载阶段

将类的字节码载入方法区中,内部采用 C++ 的 instanceKlass 描述 java 类,它的重要 field 有:

_java_mirror 即 java 的类镜像,例如对 String 来说,就是 String.class,作用是把 klass 暴露给 java 使用
_super 即父类
_fields 即成员变量
_methods 即方法
_constants 即常量池
_class_loader 即类加载器
_vtable 虚方法表
_itable 接口方法表
  • 如果这个类还有父类没有加载,先加载父类
  • 加载和链接可能是交替运行的

注意

instanceKlass 这样的【元数据】是存储在方法区(1.8 后的元空间内),但 _java_mirror是存储在堆中可以通过前

面介绍的 HSDB 工具查看

链接
验证

验证类是否符合 JVM规范,安全性检查(例如用 UE 等支持二进制的编辑器修改 HelloWorld.class 的魔数,在控制台运行异常)

准备

javap -v -p class文件路径 //反编译

  • 为 static 变量分配空间,设置默认值
  • static 变量在 JDK 7 之前存储于 instanceKlass 末尾,从 JDK 7 开始,存储于 _java_mirror (类对象)末尾
  • static 变量分配空间和赋值是两个步骤,分配空间在准备阶段完成,赋值在初始化阶段完成
  • 如果 static 变量是 final 的基本类型,以及字符串常量,那么编译阶段值就确定了,赋值在准备阶段完成
  • 如果 static 变量是 final 的,但属于引用类型,那么赋值也会在初始化阶段完成

解析

将常量池中的符号解析为直接引用。

初始化

()V 方法 【类的构造方法】

初始化即调用 ()V ,虚拟机会保证这个类的『构造方法』的线程安全

发生的时机

概括得说,类初始化是【懒惰的】

  • main 方法所在的类,总会被首先初始化
  • 首次访问这个类的静态变量或静态方法时
  • 子类初始化,如果父类还没初始化,会引发
  • 子类访问父类的静态变量,只会触发父类的初始化
  • Class.forName
  • new 会导致初始化
不会导致类初始化的情况
  • 访问类的 static final 静态常量(基本类型和字符串)不会触发初始化
  • 类对象.class 不会触发初始化
  • 创建该类的数组不会触发初始化

类加载器

双亲委派模式

所谓的双亲委派,就是指调用类加载器的 loadClass 方法时,查找类的规则 ,防止恶意篡改类,保证了类的唯一。

//loadclass实现双亲委派模式的算法
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// 1. 检查该类是否已经加载
Class<?> c = findLoadedClass(name);
	if (c == null) {
	long t0 = System.nanoTime();
	try {
		if (parent != null) {
// 2. 有上级的话,委派上级 loadClass
			c = parent.loadClass(name, false);
		}else {
// 3. 如果没有上级了(ExtClassLoader),则委派
		BootstrapClassLoader c = findBootstrapClassOrNull(name);
		}
	} catch (ClassNotFoundException e) {}
	if (c == null) {
	long t1 = System.nanoTime();
// 4. 每一层找不到,调用 findClass 方法(每个类加载器自己扩展)来加载
	c = findClass(name);
// 5. 记录耗时
	sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
	sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
    sun.misc.PerfCounter.getFindClasses().increment();
	}
}
	if (resolve) {
		resolveClass(c);
	}
	return c;
	}
}

启动类加载器

根据虚拟机参数 -Xbootclasspath 表示设置 bootclasspath

其中 /a:. 表示将当前目录追加至 bootclasspath

  • java -Xbootclasspath:
  • java -Xbootclasspath/a:<追加路径>
  • java -Xbootclasspath/p:<追加路径>

扩展类加载器

将 jar 包拷贝到 JAVA_HOME/jre/lib/ext 目录下,启动 Jar 包,其包含的类就采用扩展类加载器加载。

应用程序类加载器

用户指定的类路径下的类采用此类加载器加载。

自定义类加载器

什么时候需要自定义类加载器?

1)想加载非 classpath 随意路径中的类文件
2)都是通过接口来使用实现,希望解耦时,常用在框架设计
3)这些类希望予以隔离,不同应用的同名类都可以加载,不冲突,常见于 tomcat 容器
步骤

  1. 继承 ClassLoader 父类
  2. 要遵从双亲委派机制,重写 findClass 方法
    注意不是重写 loadClass 方法,否则不会走双亲委派机制
  3. 读取类文件的字节码
  4. 调用父类的 defineClass 方法来加载类
  5. 使用者调用该类加载器的 loadClass 方法

打破双亲委派机制----SPI

JDK提供了一种帮第三方实现者加载服务(如数据库驱动,日志库)的便捷方式,只要遵循约定,在Jar包中把类名写

在/META-INF文件夹里,在调用forName加载,当前类的ClassLoader是没办法加载的,那么就把他加载到当前线程的

线程上下文加载器【属于应用程序加载器】。

  • JDBC 的 驱动类

classpath/a:<追加路径>**

  • java -Xbootclasspath/p:<追加路径>

扩展类加载器

将 jar 包拷贝到 JAVA_HOME/jre/lib/ext 目录下,启动 Jar 包,其包含的类就采用扩展类加载器加载。

应用程序类加载器

用户指定的类路径下的类采用此类加载器加载。

自定义类加载器

什么时候需要自定义类加载器?

1)想加载非 classpath 随意路径中的类文件
2)都是通过接口来使用实现,希望解耦时,常用在框架设计
3)这些类希望予以隔离,不同应用的同名类都可以加载,不冲突,常见于 tomcat 容器
步骤

  1. 继承 ClassLoader 父类
  2. 要遵从双亲委派机制,重写 findClass 方法
    注意不是重写 loadClass 方法,否则不会走双亲委派机制
  3. 读取类文件的字节码
  4. 调用父类的 defineClass 方法来加载类
  5. 使用者调用该类加载器的 loadClass 方法

打破双亲委派机制----SPI

JDK提供了一种帮第三方实现者加载服务(如数据库驱动,日志库)的便捷方式,只要遵循约定,在Jar包中把类名写

在/META-INF文件夹里,在调用forName加载,当前类的ClassLoader是没办法加载的,那么就把他加载到当前线程的

线程上下文加载器【属于应用程序加载器】。

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

Java面试必备,JVM核心知识点总结! 的相关文章

  • 按键时关闭 ModalWindow

    我希望能够在用户按下某个键 在我的例子中是 ESC 时关闭 ModalWindow 我有一个用于按键的 Javascript 侦听器 它调用取消按钮 ID 的单击事件 jQuery modalWindowInfo closeButtonId
  • Java中有没有一种方法可以通过名称实例化一个类?

    我正在寻找问题 从字符串名称实例化一个类 https stackoverflow com questions 9854900 instantiate an class from its string name它描述了如何在有名称的情况下实例
  • 如何让 BlazeDS 忽略属性?

    我有一个 java 类 它有一个带有 getter 和 setter 的字段 以及第二对 getter 和 setter 它们以另一种方式访问 该字段 public class NullAbleId private static final
  • 序列的排列?

    我有具体数量的数字 现在我想以某种方式显示这个序列的所有可能的排列 例如 如果数字数量为3 我想显示 0 0 0 0 0 1 0 0 2 0 1 0 0 1 1 0 1 2 0 2 0 0 2 1 0 2 2 1 0 0 1 0 1 1 0
  • 为 java 游戏创建交互式 GUI

    大家好 我正在创建一个类似于 java 中的 farmville 的游戏 我只是想知道如何实现用户通常单击以与游戏客户端交互的交互式对象 按钮 我不想使用 swing 库 通用 Windows 看起来像对象 我想为我的按钮导入自定义图像 并
  • 如何在 Spring 中禁用使用 @Component 注释创建 bean?

    我的项目中有一些用于重构逻辑的通用接口 它看起来大约是这样的 public interface RefactorAwareEntryPoint default boolean doRefactor if EventLogService wa
  • jQuery AJAX 调用 Java 方法

    使用 jQuery AJAX 我们可以调用特定的 JAVA 方法 例如从 Action 类 该 Java 方法返回的数据将用于填充一些 HTML 代码 请告诉我是否可以使用 jQuery 轻松完成此操作 就像在 DWR 中一样 此外 对于
  • 在 Jar 文件中运行 ANT build.xml 文件

    我需要使用存储在 jar 文件中的 build xml 文件运行 ANT 构建 该 jar 文件在类路径中可用 是否可以在不分解 jar 文件并将 build xml 保存到本地目录的情况下做到这一点 如果是的话我该怎么办呢 Update
  • Java 公历日历更改时区

    我正在尝试设置 HOUR OF DAY 字段并更改 GregorianCalendar 日期对象的时区 GregorianCalendar date new GregorianCalendar TimeZone getTimeZone GM
  • Java 集合的并集或交集

    建立并集或交集的最简单方法是什么Set在 Java 中 我见过这个简单问题的一些奇怪的解决方案 例如手动迭代这两个集合 最简单的单行解决方案是这样的 set1 addAll set2 Union set1 retainAll set2 In
  • Hibernate 的 PersistentSet 不使用 hashCode/equals 的自定义实现

    所以我有一本实体书 public class Book private String id private String name private String description private Image coverImage pr
  • 像 Java 这样的静态类型语言中动态方法解析背后的原因是什么

    我对 Java 中引用变量的动态 静态类型和动态方法解析的概念有点困惑 考虑 public class Types Override public boolean equals Object obj System out println i
  • Spring Boot Data JPA 从存储过程接收多个输出参数

    我尝试通过 Spring Boot Data JPA v2 2 6 调用具有多个输出参数的存储过程 但收到错误 DEBUG http nio 8080 exec 1 org hibernate engine jdbc spi SqlStat
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • java for windows 中的文件图标叠加

    我正在尝试像 Tortoise SVN 或 Dropbox 一样在文件和文件夹上实现图标叠加 我在网上查了很多资料 但没有找到Java的解决方案 Can anyone help me with this 很抱歉确认您的担忧 但这无法在 Ja
  • 如何使用 jUnit 将测试用例添加到套件中?

    我有 2 个测试类 都扩展了TestCase 每个类都包含一堆针对我的程序运行的单独测试 如何将这两个类 以及它们拥有的所有测试 作为同一套件的一部分执行 我正在使用 jUnit 4 8 在 jUnit4 中你有这样的东西 RunWith
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • 在java中为组合框分配键

    我想添加一个JComboBox在 Swing 中这很简单 但我想为组合中的每个项目分配值 我有以下代码 JComboBox jc1 new JComboBox jc1 addItem a jc1 addItem b jc1 addItem
  • 使用 svn 1.8.x、subclise 1.10 的 m2e-subclipse 连接器在哪里?

    我读到 m2e 的生产商已经停止生产 svn 1 7 以外的任何版本的 m2e 连接器 Tigris 显然已经填补了维护 m2e subclipse 连接器的空缺 Q1 我的问题是 使用 svn 1 8 x 的 eclipse 更新 url
  • 如何防止在Spring Boot单元测试中执行import.sql

    我的类路径中有一个 import sql 文件 其中包含一些 INSERT 语句 当使用 profile devel 运行我的应用程序时 它的数据被加载到 postgres 数据库中 到目前为止一切正常 当使用测试配置文件执行测试时 imp

随机推荐

  • 华为OD机试 - 单词倒序(Java)

    题目描述 输入单行英文句子 里面包含英文字母 空格以及 三种标点符号 请将句子内每个单词进行倒序 并输出倒序后的语句 输入描述 输入字符串S S的长度 1 N 100 输出描述 输出倒序后的字符串 备注 标点符号左右的空格 0 单词间空格
  • C语言 -- 动态数组&链表

    目录 动态数组 动态数组的实现 用户test 链表 目的 链表的结构体 链表的实现 初始化链表 插入节点 遍历链表 删除节点 清空链表 销毁链表 用户回调函数 给用户提供接口获取链表长度 用户test 动态数组 将数组开辟到堆区 实现动态扩
  • ubuntu 16.04安装 jdk 1.9

    1 命令行输入javac 提示java尚未安装 选择提示中的包进行安装 2 执行 sudo apt install 安装jdk的版本号 根据提示确认安装 3 配置jdk路径 执行 sudo gedit etc profile 输入密码打开文
  • c++ STL vector知识点

    c 知识点 vector基本概念及定义 vector函数的构造 vector函数实现 vector基本概念及定义 头文件 include
  • VTK入门001——HelloVTK

    include VTKPlatform h vtkConeSource 是 VTK 库中的一个类 用于生成一个圆锥体的几何形状 include
  • 网站数据分析报告怎么写?

    网站数据分析报告怎么写 1 目标 Objective 是前提 网站分析报告的起点不是从现象开始的 而是从网站的目标 objective 开始的 我相信大多数网站的目标不应该超过1个 那些各种目标都应该归结为一个最终的最根本的目标 如果你的老
  • CTF show 萌新web-1

    首先看题目 代码整体逻辑是先通过GET请求传递参数id 如果id大于999 报错 如果小于999 则输出当前的执行的sql语句 如果根据id参数能在数据库中查到值 row 则将其打印出来 而flag则是id为1000的 row中的内容 这道
  • excel表格(.csv)保存到数据库--QT数据库

    刚学QT的菜鸟 无聊的时候总会找一点事情做 言归正传 将excel表格保存到数据库 是比较简单的 我的想法简单粗暴 从路径中获取文件 通过按键控制加载 将大象放进冰箱需要是三步 这个同样 1 获取路径 2 读取Excel文件 3 将其保存到
  • Domain-Specific Languages 23

    Domain Specific Languages Whenever you listen to a discussion by experts in any domain be it chess players kindergarten
  • 红日靶场(五)

    红日5 一 环境搭建 此次靶场虚拟机共用两个 一个外网一个内网 用来练习红队相关内容和方向 主要包括常规信息收集 Web攻防 代码审计 漏洞利用 内网渗透以及域渗透等相关内容学习 1 环境拓扑图 2 靶机下载地址 漏洞详情 3 我们设置VM
  • elasticsearch 集群配置

    主节点配置 集群名称 cluster name demo 节点名称 每个节点的名称不能重复 node name es node 1 ip 地址 每个节点的地址不能重复 network host 172 16 10 1 是不是有资格主节点 n
  • Python-schema的使用

    不管我们做什么应用 只要和用户输入打交道 就有一个原则 永远不要相信用户的输入数据 意味着我们要对用户输入进行严格的验证 web开发时一般输入数据都以JSON形式发送到后端API API要对输入数据做验证 一般我都是加很多判断 各种if 导
  • Python生成随机数,并将生成的随机数组成10道加减乘除的基本算术题目

    编写一个小学生算术能力测试题 提供10道加减乘除四种基本算术运算的题目 联系者根据显示的题目输入自己的答案 程序自动判断输入的答案是否正确并显示出相应的信息 生成一到一百的随机数 import random x random randint
  • SRM系统是什么?

    SRM全称Supplier Relationship Management 即供应商关系管理 SRM管理系统即供应商关系管理系统 供应商管理系统是采购管理系统的一个子系统 也是采购管理系统的一个重要模块 是用于改进企业与供应商关系的联系 完
  • Mysql主键约束和唯一约束

    Mysql约束 1 作用 约束定义为确保数据完整性必须遵循的规则 约束可以在创建表的过程中创建 也可以稍后再添加 在创建表后添加约束时 它将检查现有数据以确定其是否违背该约束 如果现有数据违背了将添加的约束 那么将不会向指定列施加该约束 2
  • 找不到文件、主类名和文件名不一致、缺少分号的解决方法

    1 找不到文件 解决方法 源文件名不存在或写错 或者当前路径错误 2 主类名和文件名不一致 解决方法 声明为public的主类应与文件名一致 否则编译失败 3 缺少分号 解决方法 编译失败 注意错误出现的行数 再到源代码中指定位置改错
  • shell实例流程控制&函数

    条件 if then elif then fi if的条件部分经常使用test EXPRESSION或 EXPRESSION 实现 test的用法可以参见test if 条件1 if 条件1 then then 执行语句1 elif 条件2
  • MetaMask安装使用指南

    前言 MetaMask是一个以太坊钱包插件 虽然只能在Chrome浏览器中使用 但作为以太坊钱包的metamask却很受以太坊开发者欢迎 MetaMask除了是一个简单的钱包 它主要卖点是让使用者可以很容易跟以太坊的智能合约互动 或者说说M
  • DLUT C++上机作业(实验六)

    注意 博客所有代码在VS上均能编译通过 codeblocks等编译器可能因为某些变量名无法识别而无法编译 我的VS上不能用end做变量名就很迷呀 2 有一个交通工具类vehicle 将它作为基类派生小车类car 卡车类truck和轮船类bo
  • Java面试必备,JVM核心知识点总结!

    JVM基础 程序计数器 Program Counter Register CPU中的寄存器 作用 记住下一条JVM指令 特点 线程私有 唯一一个不会出现内存溢出的区域 虚拟机栈 Java virtual mechine Stack 线程私有