jvm原理

Java内存

試著忘記壹切 提交于 2020-02-06 16:06:36
Java 虚拟机在执行 Java 程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java 虚拟机规范将 JVM 所管理的内存分为以下几个运行时数据区:程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区。 一,内存区域划分   1.线程共享区域:     (1)Java堆(对象实例),GC的主要区域,会出现OutOfMemoryError     (2)方法区(加载的类信息,常量,静态变量,即时编译器编译后的代码)会出现OutOfMemoryError   2.线程私有区域:     (1)虚拟机栈(操作数栈,动态链接,方法返回地址,局部变量)       用于支持虚拟机进行方法方法调用和方法执行的数据结构。生命周期与线程相同,每个方法执行时会创建一个栈帧并入栈,对于执行引擎,活动线程中,只有栈顶的栈帧是有效的,称为当前栈帧,所关联的方法称为当前方法。       如果申请的栈深度大于虚拟机允许的栈深度则抛出StackOutflowError       如果在动态扩展时,无法申请到足够的内存则抛出OutOfMemoryError       单线程:无论是栈空间太大,还是虚拟机内存太小,抛出的都是StackOutflowError       多线程:抛出OutOfMemoryError         局部变量表:是一组变量值存储空间

Java Agent 调试,Java agent debug

∥☆過路亽.° 提交于 2020-02-03 02:09:52
Java Agent 调试,agent debug 一、简介 Java agent 是在另外一个 Java 应用(“目标”应用)启动之前要执行的 Java 程序,这样 agent 就有机会修改目标应用或者应用所运行的环境。修改环境的时候做到对于项目中的代码没有入侵性,不需要修改老项目代码即可实现想要的能力,比如常见的skywoking,就是通过这样的方式实现的。比如这篇文章 通过修改字节码实现Java Agent 通过使用 Byte Buddy,便捷地创建 Java Agent 。还有一些功能,比如热更新、arthas 替换class字节码等等。 问题 Java agent的实现原理是什么? Java agent 如何调试呢?习惯了现在的直接代码调试?对于agent 有点慌。 二、原理 Java agent 主要是通过Instrumentation实现的。 Instrumentation 简介 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中解放出来,使之可以用 Java 代码的方式解决问题。使用 Instrumentation,开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义

多线程面试60题超详解

久未见 提交于 2020-01-31 09:24:54
多线程面试60题 1.多线程有什么用? 2.线程和进程的区别是什么? 3.Java 实现线程有哪几种方式? 4.启动线程方法 start()和 run()有什么区别? 5.怎么终止一个线程? 6.一个线程的生命周期有哪几种状态?它们之间如何流转的? 7.线程中的 wait()和 sleep()方法有什么区别? 8.多线程同步有哪几种方法? 9.什么是死锁?如何避免死锁? 10.多线程之间如何进行通信? 11、线程怎样拿到返回结果? 12、violatile 关键字的作用? 13、新建 T1、T2、T3 三个线程,如何保证它们按顺序执行? 14、怎么控制同一时间只有 3 个线程运行? 15、为什么要使用线程池? 16、常用的几种线程池并讲讲其中的工作原理。 什么是线程池? 线程池的好处 如何提交线程 submit 和 execute 分别有什么区别呢? 如何关闭线程池es.shutdown()? 17、线程池启动线程 submit()和 execute()方法有什么不同? 18、CyclicBarrier 和 CountDownLatch 的区别? 19、什么是活锁、饥饿、无锁、死锁? 20、什么是原子性、可见性、有序性? 21、什么是守护线程?有什么用? 什么是守护线程? 22、一个线程运行时发生异常会怎样? 23、线程 yield()方法有什么用? 24、什么是重入锁? 25

java中常用的锁机制

*爱你&永不变心* 提交于 2020-01-28 20:44:38
基础知识 基础知识之一:锁的类型 锁就那么几个,只是根据特性,分为不同的类型 锁的概念 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。锁旨在强制实施互斥排他、并发控制策略。 锁通常需要硬件支持才能有效实施。这种支持通常采取一个或多个原子指令的形式,如"test-and-set", "fetch-and-add" or "compare-and-swap"”。这些指令允许单个进程测试锁是否空闲,如果空闲,则通过单个原子操作获取锁。 锁的三个概念 1、锁开销 lock overhead 锁占用内存空间、 cpu初始化和销毁锁、获取和释放锁的时间。程序使用的锁越多,相应的锁开销越大 2、锁竞争 lock contention 一个进程或线程试图获取另一个进程或线程持有的锁,就会发生锁竞争。锁粒度越小,发生锁竞争的可能性就越小 3、死锁 deadlock 至少两个任务中的每一个都等待另一个任务持有的锁的情况锁粒度是衡量锁保护的数据量大小,通常选择粗粒度的锁(锁的数量少,每个锁保护大量的数据),在当单进程访问受保护的数据时锁开销小,但是当多个进程同时访问时性能很差。因为增大了锁的竞争。相反,使用细粒度的锁(锁数量多,每个锁保护少量的数据)增加了锁的开销但是减少了锁竞争。例如数据库中,锁的粒度有表锁、页锁、行锁、字段锁

面经系列之 java基础

怎甘沉沦 提交于 2020-01-25 07:50:34
java基础 java基础 1 值传递和引用传递 2 为什么重写equals()时也要重写hashcode() 3 java面向对象特性 4 java和c++的区别 5 多态的实现原理 1 类调用 1)静态绑定 2)动态绑定 2 接口调用 6 抽象类和接口的区别以及使用场景 7 忘了之前要写啥了 8 反射 1)反射概述 2)获取class文件对象的三种方式: 3)反射机制的相关类 4)示例 9 注解 1)概述 2)四种标准元注解 3)示例 10 内部类 1)静态内部类 2)成员内部类 3)局部内部类 4) 匿名内部类 11 泛型 1)泛型方法 2)泛型类 12 java序列化(创建可复用的java对象) 13 java复制 1)直接复制赋值 2)浅复制 3)深复制 java基础 1 值传递和引用传递 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。 一般认为,java内的基础类型数据传递都是值传递. java中实例对象的传递是引用传递。 首先是 基本类型与对象的比较: 四个例子: 1)基本类型 public static void main ( String [ ] args ) { int n = 10 ; foo ( n ) ; System . out .

Java面试 4.10 多线程

不想你离开。 提交于 2020-01-22 22:25:24
4.10.1 什么是线程?它与进程有什么区别?为什么要使用多线程 线程是指程序在执行过程中,能够执行程序代码的一个执行单元。 进程是指一段正在执行的程序。而线程有时也被称为轻量级进程,它是程序执行的最小单元,一个进程可以拥有多个线程,各个线程之间共享程序的内存空间(代码段、数据段和堆空间)及一些进程级的资源(例如打开的文件),但是各个线程拥有自己的栈空间。 在操作系统级别上,程序的执行都是以进程为单位的,而每个进程中通常都会有多个线程互不影响地并发执行,那么为什么要使用多线程呢?其实,多线程的使用为程序研发带来了巨大的便利,具体而言,有以下几个方面的内容: 1)使用多线程可以减少程序的响应时间。在单线程(单线程指的是程序执行过程中只有一个有效操作的序列,不同操作之间都有明确的执行先后顺序)的情况下,如果某个操作很耗时,或者陷入长时间的等待(如等待网络响应),此时程序将不会响应鼠标和键盘等操作,使用多线程后,可以把这个耗时的线程分配到一个单独的线程去执行,从而使程序具备了更好的交互性。 2)与进程相比,线程的创建和切换开销更小。由于启动一个新的线程必须给这个线程分配独立的地址空间,建立许多数据结构来维护线程代码段、数据段等信息,而运行于同一进程内的线程共享代码段、数据段,线程的启动或切换的开销比进程要少很多。同时多线程在数据共享方面效率非常高。 3)多 CPU

JVM 线程中方法执行过程

倖福魔咒の 提交于 2020-01-18 09:56:23
本章节内容参考:《深入理解Java虚拟机》 运行时数据区: 本次只介绍用于程序运行的线程私有的内存模型。 虚拟机栈(FILO):java方法执行的内存模型。   栈帧(线程执行的一个方法的内存模型,每调用一个方法,压入一个栈帧)    局部变量表:编译器可知的8种基本类型、reference类型、returnAddress类型   操作数栈:一个用于计算的临时数据存储区(明显,此栈是为了存放要操作的数据用的)    动态链接:支持java多态   返回地址:方法结束的地方。return/Exception 本地方法栈:Native方法执行的内存模型。 程序计数器:这个计数器记录的是正在执行的虚拟机字节码指令的地址(如果线程正在执行的是一个java方法)。 字节码解释器工作时,就是通过改变这个计数器的值来选取需要执行的字节码 指令(分支,循环,跳转、异常处理、线程恢复) 线程中,方法A调用方法B。 线程的执行的过程:    1、线程开始,分配虚拟机栈大小(JVM参数 -Xss:大小,1.5+默认1M), 2、执行方法A时,创建一个栈帧A压入虚拟机栈顶,根据程序计数器中的记录的下一个要执行的字节码指令的地址,找到并执行指令(将要操作的数据压入操作数栈栈顶,将操作结果放入局部变量表中,详细过程参照下面“合代码演示”部分)。 3、中间调用方法B,则创建栈帧B,接着执行方法B的指令

Tomcat参数JAVA_OPTS调整

久未见 提交于 2020-01-10 17:22:25
启动文件修改 在windows环境下,tomcat下的~/bin/catalina.bat文件,在文件头部加入: set "JAVA_OPTS=%JAVA_OPTS% -server -Xms5120m -Xmx10240m -XX:PermSize=640M -XX:MaxPermSize=2560m" 在linux环境下,tomcat下的~/bin/catalina.sh文件,在文件头部加入: JAVA_OPTS = " $JAVA_OPTS -server -Xms4096m -Xmx6144m -XX:PermSize=256m -XX:MaxPermSize=2048m" 重启tomcat,即可。 验证 可以通过访问 http://localhost:8080/manager/status 可以查看jvm的信息。tomcat的管理员配置详见tomcat管理员配置 常用参数详解: - server:一定要作为第一个参数,在多个 CPU 时性能佳,还有一种叫 - client 的模式,特点是启动速度比较快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或开发调试,在 32 位环境下直接运行 Java 程序默认启用该模式。Server 模式的特点是启动速度比较慢,但运行时性能和内存管理效率很高,适用于生产环境,在具有 64 位能力的 JDK 环境下默认启用该模式

JVM垃圾回收算法

守給你的承諾、 提交于 2020-01-10 13:48:11
转:https://www.cnblogs.com/godoforange/p/11552865.html 如何判断对象是否为垃圾对象? 1)引用计数法 在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用技术器得值就+1,当引用失效的时候,计数器得值就-1 算法缺点:循环引用无法回收。 2)可达性分析法 GCroot结点开始向下搜索,路径称为引用链,当对象没有任何一条引用链链接的时候,就认为这个对象是垃圾,并进行回收。 那么什么是GCroot呢(虚拟机在哪查找GCroot)。 虚拟机栈(局部变量表) 方法区的类属性所引用的对象。 方法区中常量所引用的对象。 本地方法栈中引用的对象。 目前主流JVM采用的垃圾判定算法就是可达性分析法。 垃圾回收算法: 1)标记-清除算法 存在的问题: 效率问题。 内存小块过多。 如图所示:黄色的就是被标记清除的。清除后会发现有很多多余的小块。 2)复制算法 下面是java内存常规划分 (线程共有)堆内存 方法区 (栈内存 本地方法栈) 程序计数器 下面是堆内存的划分 新生代 Eden 伊甸园 Survivor 存活区 Tenured Gen 养老区 老年代 下面就是过程: 被标记的黑色就是需要回收的 将白色区域复制下面,然后清空上面的 这样就完成了内存的连续分配,但是引来一个问题。 每次只能使用一半的内存。是不是有点少。。 为了解决这个问题

JVM(三)---方法区、栈开头

柔情痞子 提交于 2020-01-10 13:05:38
方法区: 方法区是亮色,代表线程共享,存在垃圾回收机制。 方法区供各线程共享的运行时内存区域。它存储了每一个类的结构信息( 类的模板 ) ,例如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容。上面讲的是规范,在不同虚拟机里头实现是不一样的, 最典型的就是永久代(PermGen space)和元空间(Metaspace)。 但是实例变量存在堆内存中,和方法区无关。 栈开头: 栈管运行,堆管存储。 程序 = 算法 + 数据结构。(书面上) 程序 = 框架 + 业务逻辑。 (工作上) 队列(FIFO): 栈(FILO):栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。8种基本类型的变量+对象的引用变量+实例方法都是在函数的栈内存中分配。 栈保存那些:8种基本类型的变量、对象的引用变量、实例方法都是在函数的栈内存中分配。 方法就是栈针。在java中叫方法,在压入栈之后就叫栈针。栈中第一个栈针一定是main,而且栈中,先进的后出,后进的先出,所以main栈针肯定最后出栈。 栈针中主要保存3类数据: 本地变量(Local Variables):输入参数和输出参数以及方法内的变量;