自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

Java

万物皆对象

  • 博客(560)
  • 收藏
  • 关注

原创 你能说出来几个垃圾收集器

1、Serial Serial收集器是Hotspot运行在Client模式下的默认新生代收集器, 它在进行垃圾收集时,会暂停所有的工 作进程,用一个线程去完成GC工作特点:简单高效,适合jvm管理内存不大的情况(十兆到百兆)。 2、Parnew ParNew收集器其实是Serial的多线程版本,回收策略完全一样,但是他们又有着不同。 我们说了Parnew是多线程gc收集,所以它配合多核心的cpu效果更好,如果是一个cpu,他俩效果就差 不多。(可用-XX:ParallelGCTh

2022-03-09 10:46:38 42

原创 JVM垃圾处理方法

1、标记-清除算法(老年代) 该算法分为“标记”和“清除”两个阶段: 首先标记出所有需要回收的对象(可达性分析), 在标记完成后统一清 理掉所有被标记的对象该算法会有两个问题: 1. 效率问题,标记和清除效率不高。 2. 空间问题: 标记清除后会产生大量不连续的内存碎片, 空间碎片太多可能会导致在运行过程中需要分 配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集。 所以它一般用于"垃圾不太多的区域,比如老年代"。 2、复制算法(新生代) 该算法的核心是将可

2022-03-09 10:45:50 141

原创 什么是分布式垃圾回收(DGC)?它是如何工作的?

DGC 叫做分布式垃圾回收。RMI 使用 DGC 来做自动垃圾回收。因为 RMI 包含了跨虚拟机的远程对象的 引用,垃圾回收是很困难的。DGC 使用引用计数算法来给远程对象提供自动内存管理。

2022-03-09 10:45:20 1045

原创 JVM 的永久代中会发生垃圾回收么?

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。 注:Java 8 中已经移除了永久代,新加了一个叫做元数据区的native 内存区。

2022-03-09 10:44:49 763

原创 简述 Java 垃圾回收机制

在 Java 中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在 JVM 中,有 一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存 不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收...

2022-03-09 10:44:19 945

原创 GC是什么?为什么要有GC

GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序 或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存 的目的,Java语言没有提供释放已分配内存的显示操作方法。 Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方 法之一:System.gc() 或Runtime.getRuntime().gc()但JVM可以屏蔽掉显示的垃圾回收调用。 垃圾回收可以有效的防

2022-03-09 10:43:49 302

原创 什么情况下会发生栈溢出?

栈的大小可以通过-Xss参数进行设置,当递归层次太深的时候,就会发生栈溢出。比如循环调用,递归 等。

2022-03-09 10:43:18 383

原创 Java的四种引用,强弱软虚

1、强引用 强引用是平常中使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式: String str = new String("str"); 2、软引用 软引用在程序内存不足时,会被回收,使用方式:// 注意:wrf这个引用也是强引用,它是指向SoftReference这个对象的, // 这里的软引用指的是指向new String("str")的引用,也就是SoftReference类中T SoftReference<String> wrf =

2022-03-09 10:43:01 140

原创 如果对象的引用被置为 null,垃圾收集器是否会立即释放对象占用的内存?

不会,在下一个垃圾回收周期中,这个对象将是可被回收的。

2022-03-09 10:42:04 388

原创 如何判断对象可以被回收?

在堆里面存放着Java世界中几乎所有的对象实例, 垃圾收集器在对堆进行回收前, 第一件事就是判断哪些 对象已死(可回收). 1、引用计数法 在JDK1.2之前,使用的是引用计数器算法。 在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,当引用失效的时 候,计数器的值就-1,当引用计数器被减为零的时候,标志着这个对象已经没有引用了,可以回收了! 问题: 如果在A类中调用B类的方法,B类中调用A类的方法,这样当其他所有的引用都消失了之后,A和B还有 一

2022-03-09 10:41:44 587

原创 类的生命周期

类的生命周期包括这几个部分,加载、连接、初始化、使用和卸载,其中前三部是类的加载的过程1、加载,查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象2、连接,连接又包含三块内容:验证、准备、初始化。 1)验证,文件格式、元数据、字节码、符号引 用验证; 2)准备,为类的静态变量分配内存,并将其初始化为默认值; 3)解析,把类中的符号引用 转换为直接引用 3、初始化,为类的静态变量赋予正确的初始值 4、使用,new出对象程序中使用 5、卸载,执行垃圾回

2022-03-08 09:17:40 114

原创 Java对象结构

Java对象由三个部分组成:对象头、实例数据、对齐填充。 1、对象头由两部分组成,第一部分存储对象自身的运行时数据:哈希码、GC分代年龄、锁标识状态、 线程持有的锁、偏向线程ID(一般占32/64 bit)。第二部分是指针类型,指向对象的类元数据类型(即 对象代表哪个类)。如果是数组对象,则对象头中还有一部分用来记录数组长度。 2、实例数据用来存储对象真正的有效信息(包括父类继承下来的和自己定义的) 3、对齐填充:JVM要求对象起始地址必须是8字节的整数倍(8字节对齐) ...

2022-03-08 09:16:57 705

原创 JVM中对象的创建过程

1、拿到内存创建指令 当虚拟机遇到内存创建的指令的时候(new 类名),来到了方法区,找 根据new的参数在常量池中定位 一个类的符号引用。 2、 检查符号引用 检查该符号引用有没有被加载、解析和初始化过,如果没有则执行类加载过程,否则直接准备为新的对 象分配内存 3、分配内存 虚拟机为对象分配内存(堆)分配内存分为指针碰撞和空闲列表两种方式;分配内存还要要保证并发安 全,有两种方式。 1)指针碰撞 所有的存储空间分为两部分,一部分是空闲,一部分是占用,需要分配空间的

2022-03-08 09:16:16 58

原创 Java类加载过程

Java 类加载需要经历一下 7 个过程: 1、加载 加载是类加载的第一个过程,在这个阶段,将完成一下三件事情: 通过一个类的全限定名获取该类的二进制流。 将该二进制流中的静态存储结构转化为方法去运行时数据结构。 在内存中生成该类的 Class 对象,作为该类的数据访问入口。 2、验证 验证的目的是为了确保 Class 文件的字节流中的信息不回危害到 虚拟机.在该阶段主要完成以下四钟验 证: 文件格式验证:验证字节流是否符合 Class 文件的规范,如 主次版本号是否在当

2022-03-08 09:15:34 299

原创 JVM加载class文件的原理机制?

JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的 Java运行时系统组件,它负责在运行时查找和装入类文件中的类。 由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java 程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加 载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与 所加载类对应的C

2022-03-08 09:14:58 28

原创 java类加载器

1、启动类加载器:Bootstrap ClassLoader 负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录,下同)下,或被-Xbootclasspath参数指定的路径中 的,并且能被虚拟机识别的类库 2、扩展类加载器:Extension ClassLoader 该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载DK\jre\lib\ext目录中,或者由 java.ext.dirs系统变量指定的路径中的所有类库(如javax.*开

2022-03-08 09:14:28 334

原创 JVM有哪些内存区域?(JVM的内存布局是什么?)

JVM包含堆、元空间、Java虚拟机栈、本地方法栈、程序计数器等内存区域。其中,堆是占用内存最大 的一块。我们平常的-Xmx、-Xms等参数,就是针对于堆进行设计的。 堆:JVM堆中的数据,是共享的,是占用内存最大的一块区域 虚拟机栈:Java虚拟机栈,是基于线程的,用来服务字节码指令的运行 程序计数器:当前线程所执行的字节码的行号指示器 元空间:方法区就在这里,非堆本地内存:其他的内存占用空间 ...

2022-03-08 09:13:57 252

原创 怎么获取 Java 程序使用的内存?堆使用的百分比?

可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。 通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。 Runtime.freeMemory() 方法返回剩余空间的字节数 Runtime.totalMemory()方法总内存的字节数 Runtime.maxMemory() 返回最大内存的字节数 ...

2022-03-08 09:13:27 578

原创 JVM内存分哪几个区,每个区的作用是什么?

Java虚拟机主要分为以下一个区: 方法区: 1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主 要是对方法区里的常量池和对类 型的卸载 2. 方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数 据。 3. 该区域是被线程共享的。 4. 方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态 性,也就是说常量并不一定是编 译时确定,运行时生成的常量也会存在这个常量池中

2022-03-08 09:12:58 297

原创 解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法

通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中 的栈空间; 而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃 圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、 Survivor(又可分为From Survivor和To Survivor)、Tenured; 方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编

2022-03-08 09:12:33 294

原创 Java 中堆和栈有什么区别?

JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在 堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。 栈 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定 义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为 该变量分配的内存空间,该内存空间可以立即被另作它用。 堆 堆内存用来存放由 new 创建的对象和数

2022-03-07 09:04:50 159

原创 Java 堆的结构是什么样子的?什么是堆中的永久代(Perm Genspace)?

JVM 的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在 JVM 启动的时候被创建。对 象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收。堆内存是由存活和死亡的对象组成的。 存活的对象是应用可以访问的,不会被垃圾回收。死亡的对象是应用不可访问尚且还没有被垃圾收集器 回收掉的对象。一直到垃圾收集器把这些 对象回收掉之前,他们会一直占据堆内存空间。...

2022-03-07 09:04:19 186

原创 Java内存分配

寄存器:我们无法控制。 静态域:static 定义的静态成员。 常量池:编译时被确定并保存在 .class 文件中的(final)常量值和一些文本修饰的符号引用(类和 接口的全限定名,字段的名称和描述符,方法和名称和描述符)。 非 RAM 存储:硬盘等永久存储空间。 堆内存:new 创建的对象和数组,由 Java 虚拟机自动垃圾回收器管理,存取速度慢。 栈内存:基本类型的变量和对象的引用变量(堆内存空间的访问地址),速度快,可以共享,但是 大小与生存期必须确定,缺乏灵活性。 .

2022-03-07 09:03:48 16

原创 Java内存结构?

方法区和堆是所有线程共享的内存区域;而java栈、本地方法栈和程序员计数器是运行是线程私有的内 存区域。 1、Java堆(Heap),是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区 域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分 配内存。 2、方法区(Method Area),方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它 用于存储已被虚拟机加载的类信息、常量、静态变量、即时

2022-03-07 09:03:18 470

原创 什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?

Java虚拟机是一个可以执行Java字节码的虚拟机进程。 Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的 平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知 道底层硬件平台的指令长度和其他特性。 ...

2022-03-07 09:02:43 104

原创 Linux环境下如何查找哪个线程使用CPU最长

这是一个比较偏实践的问题,这种问题我觉得挺有意义的。可以这么做: 1、获取项目的pid,jps或者ps -ef | grep java,这个前面有讲过 2、top -H -p pid,顺序不能改变 这样就可以打印出当前的项目,每条线程占用CPU时间的百分比。注意这里打出的是LWP,也就是操作 系统原生线程的线程号,我笔记本山没有部署Linux环境下的Java工程,因此没有办法截图演示,网友朋 友们如果公司是使用Linux环境部署项目的话,可以尝试一下。 使用"top -H -p pi

2022-03-07 09:02:13 586

原创 Hashtable的size()方法中明明只有一条语句“return count“,为什么还要做同步?

这是我之前的一个困惑,不知道大家有没有想过这个问题。某个方法中如果有多条语句,并且都在操作 同一个类变量,那么在多线程环境下不加锁,势必会引发线程安全问题,这很好理解,但是size()方法明 明只有一条语句,为什么还要加锁? 关于这个问题,在慢慢地工作、学习中,有了理解,主要原因有两点: 1、同一时间只能有一条线程执行固定类的同步方法,但是对于类的非同步方法,可以多条线程同时访 问。所以,这样就有问题了,可能线程A在执行Hashtable的put方法添加数据,线程B则可以正常调用 s

2022-03-07 09:01:42 81

原创 CyclicBarrier和CountDownLatch的区别

两个看上去有点像的类,都在 java.util.concurrent 下,都可以用来表示代码运行到某个点上,二者 的区别在于: 1、 CyclicBarrier 的某个线程运行到某个点上之后,该线程即停止运行,直到所有的线程都到达了这 个点,所有线程才重新运行; CountDownLatch 则不是,某线程运行到某个点上之后,只是给某个数 值-1而已,该线程继续运行 2、 CyclicBarrier 只能唤起一个任务, CountDownLatch 可以唤起多个任务 3、 Cycli

2022-03-07 09:01:12 682

原创 什么是乐观锁和悲观锁

1、乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总 是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量, 如果失败则表示发生冲突,那么就应该有相应的重试逻辑。 2、悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总 是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十 一,直接上了锁就操作资源了。 ...

2022-03-07 09:00:42 16

原创 生产者消费者模型的作用是什么

这个问题很理论,但是很重要: 1、通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率,这是生产者消费者模型 最重要的作用 2、解耦,这是生产者消费者模型附带的作用,解耦意味着生产者和消费者之间的联系少,联系越少越可 以独自发展而不需要收到相互的制约 ...

2022-03-07 09:00:26 254

原创 如果你提交任务时,线程池队列已满,这时会发生什么

这里区分一下: 如果使用的是无界队列LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队 列中等待执行,因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务 如果使用的是有界队列比如ArrayBlockingQueue,任务首先会被添加到ArrayBlockingQueue中, ArrayBlockingQueue满了,会根据maximumPoolSize的值增加线程数量,如果增加了线程数量还是处 理不过来,Arr

2022-03-05 09:10:46 629

原创 FutureTask是什么

FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这 个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然,由于FutureTask 也是Runnable接口的实现类,所以FutureTask也可以放入线程池中。...

2022-03-05 09:10:15 21

原创 ReadWriteLock是什么

首先明确一下,不是说ReentrantLock不好,只是ReentrantLock某些时候有局限。如果使用 ReentrantLock,可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但这样,如 果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降 低了程序的性能。 因为这个,才诞生了读写锁ReadWriteLock。ReadWriteLock是一个读写锁接口, ReentrantReadWriteLock是ReadWriteLo

2022-03-05 09:09:45 24

原创 ConcurrentHashMap的并发度是什么

ConcurrentHashMap的并发度就是segment的大小,默认为16,这意味着最多同时可以有16条线程操 作ConcurrentHashMap,这也是ConcurrentHashMap对Hashtable的最大优势,任何情况下, Hashtable能同时有两条线程获取Hashtable中的数据吗? ...

2022-03-05 09:09:14 366

原创 synchronized和ReentrantLock的区别

synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既 然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方 法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上: 1、ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁 2、ReentrantLock可以获取各种锁的信息 3、Ree

2022-03-05 09:08:44 69

原创 讲一下 synchronized 关键字的底层原理

synchronized 关键字底层原理属于 JVM 层面。 ① synchronized 同步语句块的情况 public class SynchronizedDemo { public void method() { synchronized (this) { System.out.println("synchronized 代码块"); } } }通过 JDK 自带的 javap 命令查看 SynchronizedDemo 类的相关字节码信息:首先切换到类的对应目录

2022-03-05 09:08:23 139

原创 什么是可重入锁(ReentrantLock)?

Java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为Java 类,而不是 作为语言的特性来实现。这就为Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特 性或者锁定语义。ReentrantLock 类实现了Lock ,它拥有与synchronized 相同的并发性和内存语义,但是添加了类似锁 投票、定时锁等候和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。(换 句话说,当许多线程都想访问共

2022-03-05 09:07:26 79

原创 如何避免死锁和检测

预防死锁 破坏互斥条件:使资源同时访问而非互斥使用,就没有进程会阻塞在资源上,从而不发生死锁 破坏请求和保持条件:采用静态分配的方式,静态分配的方式是指进程必须在执行之前就申请需要 的全部资源,且直至所要的资源全部得到满足后才开始执行,只要有一个资源得不到分配,也不给 这个进程分配其他的资源。 破坏不剥夺条件:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源,但是只 适用于内存和处理器资源。 破坏循环等待条件:给系统的所有资源编号,规定进程请求所需资源的顺序必须按照

2022-03-05 09:07:00 15

原创 Java中的死锁

在Java中使用多线程,就会有可能导致死锁问题。死锁会让程序一直卡住,不再程序往下执行。我们只 能通过中止并重启的方式来让程序重新执行。这是我们非常不愿意看到的一种现象,我们要尽可能避免 死锁的情况发生! 死锁的四个必要条件 1、互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如 果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用完释放。 2、请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程

2022-03-05 09:05:55 42

原创 Java中活锁和死锁有什么区别?

活锁:一个线程通常会有会响应其他线程的活动。如果其他线程也会响应另一个线程的活动,那么就有 可能发生活锁。同死锁一样,发生活锁的线程无法继续执行。然而线程并没有阻塞——他们在忙于响应 对方无法恢复工作。这就相当于两个在走廊相遇的人:甲向他自己的左边靠想让乙过去,而乙向他的右 边靠想让甲过去。可见他们阻塞了对方。甲向他的右边靠,而乙向他的左边靠,他们还是阻塞了对方。 死锁:两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时 但以不同的顺序请求同一组锁的时候

2022-03-05 09:05:03 223

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除