JVM 垃圾回收
JVM 垃圾回收一、垃圾回收概述1. 简述 Java 垃圾回收机制
在 Java中,我们不需要手动释放对象内存,由于 JVM的垃圾回收线程自动对没有引用的对象进行回收
创建对象时,GC 开始监控这个对象的地址,大小以及使用情况。
GC采用的有向图的方式记录和管理堆中的所有对象。通过这种方式确定哪些对象是 “可达的”, 哪些对象是 “不可达的”。当GC确定一些对象为“不可达”时,GC就有责任回收这些内存空间
2. 垃圾回收机制
分代复制垃圾回收
标记垃圾回收
增量垃圾回收
3. 什么是 Grabage
垃圾是指在运行程序中没有任何指针指向的这个对象,这个对象就是需要被回收的垃圾
如果不及时堆内存中的垃圾进行清理,那么这些垃圾对象所占据的内存空间会一直保留到应用程序结束,被保留的空间无法被其他对象使用。甚至肯导致内存溢出
4. 为什么需要进行 Grabage Collection
不进行垃圾回收,内存会消耗完。
碎片整理,令新对象获得连续的内存空间
STW的GC无法满足实际需求,需要对GC进行优化
5. 垃圾回收器优点
无需手动分配回收内存,降低内存泄漏,内存溢出的风险
没有垃圾回 ...
JVM 运行时数据区
JVM 运行时数据区一、 内存模型
程序计数器:记录下一条字节码执行指令,实现分支循环跳转,异常处理,线程恢复等功能
虚拟机栈:存储局部变量表、操作数栈、动态链接、方法返回地址等信息。Java方法就调用
本地方法栈:本地方法调用
堆:所有线程共享,几乎所有对象示例都在堆中分配
方法区:用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据
二、栈和堆区别
物理地址
堆:对象分配物理地址不连续,性能相对栈弱些
GC考虑分配不连虚,产生算法提升性能:标记—消除、复制、标记—压缩、分代
栈:先进后出,物理地址连续,性能相对堆好些
内存分配
堆:在运行时分配,大小不固定
栈:局部变量,操作数,动态链接,方法返回地址等信息,程序方法的执行
程序可见性
堆:所有线程共享,可见
栈:线程私有,只对线程可见,生命周期和线程相同
浅拷贝:增加一个指针指向已有的内存地址
深拷贝:增加一个指针指向新开辟的一块内存空间
原内存发生变化,浅拷贝也随之变化;深拷贝则不会随之改变
静态变量 —> 方法区
静态对象 —> 堆
三、程序计数器 PC寄存器特 ...
JVM 架构、类加载子系统和执行引擎
JVM 架构、类加载子系统和执行引擎一、简介
jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。
jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。
jvm屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
JDK(Java Development Kit),是开发者用来编译、调试程序用的开发包。JDK也是JAVA程序需要在JRE上运行。
JRE(Java Runtime Environment),也就是java平台。所有的java程序都要在JRE环境下才能运行。
JVM(Java Virtual Machine),是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用 ...
JAVA 8 新特性
JAVA 8 新特性一、Lambda 表达式
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。
lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
1234567891011121314// 1. 不需要参数,返回值为 5 () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x // 3. 接受2个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 (int x, int y) -> x + y / ...
JAVA 线程安全集合
JAVA 线程安全集合一、线程安全
线程安全
就是当多线程访问时,采用了加锁的机制;即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读取完之后,其他线程才可以使用。防止出现数据不一致或者数据被污染的情况。
线程不安全
就是不提供数据访问时的数据保护,多个线程能够同时操作某个数据,从而出现数据不一致或者数据污染的情况。
线程安全 工作原理:
jvm中有一个main memory对象,每一个线程也有自己的working memory,一个线程对于一个变量variable进行操作的时候, 都需要在自己的working memory里创建一个copy,操作完之后再写入main memory。当多个线程操作同一个变量variable,就可能出现不可预知的结果。而用synchronized的关键是建立一个监控monitor,这个monitor可以是要修改的变量,也可以是其他自己认为合适的对象(方法),然后通过给这个monitor加锁来实现线程安全,每个线程在获得这个锁之后,要执行完加载load到working memory 到 use &&am ...
JAVA 并发相关
JAVA 并发相关一、乐观锁和悲观锁
悲观锁:
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。再比如Java里面的同步原语synchronized关键字的实现也是悲观锁。
乐观锁:
顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。
乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
Java在JDK1.5之前都是靠 synchronized关键字保证同步的,这种通过使用一致的锁定协议来协调对共享状态的访问,可以确保无论哪个线程持有共享变量的锁,都采用独占的方式来访问这些变量。这就是 ...
JAVA 线程并发和安全
JAVA 线程并发和安全一、线程不安全先来看一个例子
1234567891011121314151617public class Test { private int num = 0; public void increase(){ num++; System.out.println("当前线程:"+Thread.currentThread().getName()+" ============> "+ num); } public static void main(String[] args) { Test test = new Test(); int num = 0; for (int i = 1; i <= 3000; i++) { new Thread(test::increase, String.valueOf(i)).start(); } ...
JAVA 多线程编程
JAVA 多线程编程一、线程和进程进程:是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。
线程:是进程的一个执行路径,一个进程中至少有一个线程,进程中的多个线程共享进程的 资源。
虽然系统是把资源分给进程,但是CPU很特殊,是被分配到线程的,所以线程是CPU分配的基本单位。
二者联系一个进程中有多个线程,多个线程共享进程的堆和方法区资源,但是每个线程有自己的程序计数器和栈区域。
程序计数器:是一块内存区域,用来记录线程当前要执行的指令地址 。
栈:用于存储该线程的局部变量,这些局部变量是该线程私有的,除此之外还用来存放线程的调用栈祯。
堆:是一个进程中最大的一块内存,堆是被进程中的所有线程共享的。
方法区:则用来存放 NM 加载的类、常量及静态变量等信息,也是线程共享的 。
二者区别进程:有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。
线程:是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。
简而言之,一个程序至少有一个进程,一个进程至少有一个线程。
线程的划分尺度 ...
概说JAVA 23种设计模式
概说JAVA 23种设计模式1. 单例模式单例模式,它的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。
单例模式具备典型的3个特点:1、只有一个实例。 2、自我实例化。 3、提供全局访问点。
因此当系统中只需要一个实例对象或者系统中只允许一个公共访问点,除了这个公共访问点外,不能通过其他访问点访问该实例时,可以使用单例模式。
单例模式的主要优点就是节约系统资源、提高了系统效率,同时也能够严格控制客户对它的访问。也许就是因为系统中只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责原则”,同时也没有抽象类,所以扩展起来有一定的困难。其UML结构图非常简单,就只有一个类,如下图:
2. 工厂方法模式作为抽象工厂模式的孪生兄弟,工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,也就是说工厂方法模式让实例化推迟到子类。
工厂方法模式非常符合“开闭原则”,当需要增加一个新的产品时,我们只需要增加一个具体的产品类和与之对应的具体工厂即可,无须修改原有系统。同时在工厂方法模式中用户只需要知道生产产品的具体工厂即可,无须关系产品的创建过程,甚至连具体的产品 ...
设计模式和设计模式原则
设计模式和设计模式原则一、设计模式
“设计模式”这个术语最初并不是出现在软件设计中,而是被用于建筑领域的设计中。
1. 设计模式的概念软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。
2. 学习设计模式的意义设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。
正确使用设计模式具有以下优点。
可以提高程序员的思维能力、编程能力和设计能力。
使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
3. 设计模式的四个要素
模式名称
每一个模式都有自己的名字,通常用一两个词来描述,可以根据模式的问 ...