java
文章平均质量分 68
java进阶
计算机王
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
展开
-
java中gc实现并发标记
cms写后屏障+增量更新增量更新跟记忆集差不多,然后卡表是记忆集的实现,增量更新用的是脏页卡表就是看图需要理解漏标public calss a{Objecte b = new Object();}public class b{Object a = null;}b.a=a.b;a.b=null漏标就是 对象a被三色标记标记为黑色,然后对象a里面的属性b被设置为null了设置null之前还把之给了b.a这就是漏标然后上面是卡表的算法逻辑然后是脏页,脏页可以理解为对象是很多的依次遍历是很耗原创 2022-04-13 22:53:06 · 640 阅读 · 0 评论 -
实现三色标记算法
上图是一个栈栈的实现方式:1、把所有数据封装成一个对象2、直接存放数据第一种实现起来简单而jvm中是使用的第二种使用第二种就有一个问题无法区分是一个数字还是一个内存地址,jvm区分内存地址使用了栈图,栈图是由抽象解析器记录的,抽象解析器就是一个用来记录局部变量表与操作数栈中的数据的类型的,比如iconst_1把1压入操作数栈,这时抽象解析器会记录一个状态基本类型的状态用v表示引用类型用r表示这是在栈帧中,new这个操作是申请一块空间它被抽象解析器记录为空字符invokespecial调用构造方.原创 2022-04-12 00:16:08 · 551 阅读 · 0 评论 -
实现STW
在java虚拟机中使用的是Linux处理信号的机制中的段信号使用kill -l指令可以看linux中有那些信号,段信号是11然后java在编译的时候会写很多安全点,安全点就是出发段异常,jvm是通过把内存设置为不可读实现的触发段异常就是使用mmp申请一快空间当出发stw是把mmp的内存空间设置为不可读然后让每个线程去读这个内存这时触发段异常,触发段异常之后会执行捕获异常的函数这个东西需要我们自己捕获不然程序就停了,捕获之前需要先注册。注册捕获异常的函数signal(这里写要捕获的异常段异常为11, 这里原创 2022-04-07 23:47:50 · 800 阅读 · 0 评论 -
Stream类API
map方法public static void main(String[] args) { List<String> list1 = new ArrayList(); for(long i = 0; i < 10; i++){ list1.add(i+""); } List<Integer> list2 = list1.stream().map(e -> Integer.parseInt(e)).collect(Colle原创 2022-04-07 19:16:19 · 210 阅读 · 0 评论 -
搭建windows内核调试、malloc执行流程、线程数据结构、进程数据结构
首先安装VMware虚拟机在VMware中安装windowsXP系统安装玩之后然后打开c盘然后通过工具中的文件选项中查看页签里的高级设置吧后缀与隐藏的文件都显示出来,然后打开boot.ini文件,然后把下面的文字复制到boot.ini中把原来的内容覆盖掉。[boot loader]timeout=30default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS[operating systems]multi(0)disk(0)rdisk(0)partit原创 2022-04-07 01:02:13 · 1533 阅读 · 0 评论 -
偏向锁源码
偏向锁对应的c/c++代码是BiasedLocking 这个文件然后我们进入这个文件中去可以看到一个init函数函数注释中文意思//如果偏向锁是启用的,调度一个任务来触发一些//开启偏置锁定的运行秒数//当前加载的类以及将来加载的类。这是一个//解决方案启动时间倒退,由于大量//在虚拟机启动时获取的安全点,以撤销bias。//理想的情况是,我们可以降低消除个人偏见的成本//不需要这样的机制。就是解释延迟偏向的作用的,白话就是因为java应用程序在启动时会创建大量的安全点如果创建这些安原创 2022-03-29 00:55:12 · 599 阅读 · 0 评论 -
java实现锁的思想
前置知识:https://blog.csdn.net/qq_36301061/article/details/121801532aqs实现aqs核心实现可以分六个功能:抢锁、释放锁、入队、出队、阻塞、唤醒根据参考ReentrantLock的实现抢锁它的核心是判断阻塞队列中有没有抢不到因抢不到锁而进去的线程下图就是抢锁的核心代码 首先判断同步阻塞队列中有没有线程下面return的逻辑 大概就是判断阻塞队列的首节点的next指针是不是null如果不是说明阻塞队列中以及存在线程了,首先是h!=t也就原创 2022-03-18 23:51:02 · 338 阅读 · 0 评论 -
java的Thread类start0方法源码
带着几个问题去看源码1、如何找到native方法的源码2、Java的Thread对象、JavaThread、OSThread、操作系统线程3、Java线程与操作系统线程的关联4、Java线程保存了哪些操作系统线程数据5、怎么执行到run方法的首先第一个问题native的方法是通过jin与c/c++进行通信的jin有个规则一个java类中有native方法那么就会有一个.h的文件.h文件是c/c++用来定义变量、方法的所以想看native方法的源码可以直接去jdk源码搜索类名找它的.c或.cpp文原创 2022-03-17 02:02:17 · 3197 阅读 · 1 评论 -
手写线程池(一)
线程池实现原理:想明白线程池的原理就需要先理解条件变量条件变量需要跟互斥锁一起使用,为什么要一起使用?目前还不理解百度上没人写人话互斥锁就是加锁只有两种状态锁定和非锁定,条件变量是让一个线程进入阻塞想不懂它俩为什么要一起用,以后懂了回头再写然后互斥锁的api(linux的)// 声明一个锁类型pthread_mutex_t// 锁的属性pthread_mutex_attr_t // 属性有下面三个 PTHREAD_MUTEX_NORMAL // 抢不到锁就进入阻塞 PTHR原创 2022-03-16 00:08:17 · 187 阅读 · 0 评论 -
linux线程
线程的状态joinable(读音 找嗯的波)与detached(读音 第它吃特 分离线程)joinable线程结束资源不会回收 需要手动回收detached线程结束可以回收资源回收资源就是线程执行的方法中定义的描述符比如文件流、socket回收就是把它们的内存释放pthread_join 函数对于joinable是有效的 对于detached是无效的主控线程跟进程一起启动的线程叫做主控线程main线程指的主控线程是一个逻辑线程程序中的线程,在java中的main线程是一个joinable类原创 2022-03-15 01:10:29 · 468 阅读 · 0 评论 -
寄存器(二)
Intel CPU 的发展史吧:Intel CPU 系列,最初是 4 位微处理器 4004,然后到到 8 位微处理器的 8008 ,再到 8 微微处理器 8080,以及稍后的 16 位微处理器 8086,由 8086 开始,Intel 进入现在所谓的 x86 时代 。Intel 8086 为 16 位 CPU ,而因为在 8086 之前的 CPU 都是 8 位 CPU,这样也就造成了很多的外设也只支持 8 位,因此 Intel 紧接着就退出了 8 位的 8088 CPU,因此 In原创 2022-03-08 23:54:55 · 1606 阅读 · 0 评论 -
寄存器(一)
寄存器:在8086CPU中一共有14个寄存器:ax,bx,cx,dx,si,di,sp,bp,ip,cs,ss,ds,es,flag每个寄存器都是16位,在下面对各个寄存器的逐一介绍中,根据功能或者其特点可能会将几个寄存器划分在一起介绍(所以一个寄存器可能会出现在多个地方,最后会给出总结表)通用寄存器(ax,bx,cx,dx)将它们4个划分一起是由于它们的一个共同特性:都可以分为独立使用的2个8位寄存器来使用ax:ah,albx:bh,blcx:ch,cldx,dh,dlh结束的为高位原创 2022-03-08 23:55:02 · 4143 阅读 · 0 评论 -
JIT即时编译器
java是半编译半解释性语言编译就是把代码编译成机器码解释就是在代码运行的时候随着运行随着编译成机器码机器码就是二进制java的半编译半解释体现在javac编译,java运行还有运行期即时编译(c1或c2)+解释执行java有两种解释器字节码解析器与模板解析器解释器就是把代码中的关键字翻译成机器码 比如new关键字在字节码解释器中它对应jvm中的一个switch分支这个分支中做的事情就是分配内存等操作 而java中一共有200多个关键字 这一段switch是很长的 它还会循环遍历代码中的关原创 2022-03-07 23:32:12 · 455 阅读 · 0 评论 -
STW&OopMap&安全点
stw原理让线程停止的方式test %eax, os::_polling_page 往寄存器设置无用的数据然后test汇编指令会设置寄存器状态 当要发生stw时它会把内存叶变成不可写这时就会触发操作系统的异常 然后线程就能停止了 线程到安全点的时间就是用户线程到执行test %eax, os::_polling_page的时间OopMap用来存储根对象(GC root)它会在使用对象之前把它存起来 用来做gcroot扫描的入口...原创 2022-03-04 20:24:08 · 687 阅读 · 0 评论 -
jvm内存池
内存池为什么jvm要创建内存池?申请内存需要操作系统去做如果java程序运行时再通过操作系统申请内存那效率是很慢的 这涉及到cpu用户态与内核态的切换是一个很重的操作 所以jvm做了优化在启动时申请一大片内存也就是运行时数据区 它的结构首先有一个Memory pool可以把Memory pool理解为它是内存池也是管理内存者 一块很大的连续空间Memory Chunk对应堆Memory Cell存储数据的最小结构 一个cell占8B一个对象16B就用两个cell存储 可以把cell理解为实原创 2022-03-03 00:08:45 · 558 阅读 · 0 评论 -
OOM与调优
模拟元空间OOM通过cglib包中的api动态的加载类import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class MetaspaceOverFlowTest { /** * 通过CGLIB模拟向元空间写入数据原创 2022-03-01 23:29:32 · 1015 阅读 · 0 评论 -
对象创建过程2
计算对象的大小 对象头MarkWord 8字节类型指针 32位机器是4字节 64位机器8字节(可使用指针压缩变成4字节)实例数据 实际大小看类中有无非静态成员变量对齐填充 MarkWord与类型指针与实例数据加起来是否整除8 如果不整除会计算还差多少可以被8整除 然后这个数就是对齐填充的大小还有这样的对象头如果类中有数组会并且关闭了指针压缩就会有两个对齐填充 如果开启指针压缩类型指针与数组长度的内存地址会写在一块计算对象大小public class CountSimpleObjectSi原创 2022-02-28 21:53:29 · 212 阅读 · 0 评论 -
字符串常量池
字符数组的存储方式public static void main(String[] args){ char[] arr = new char[]{'1','1'}; while(true);}数组是运行时数据(动态数据只有在运行的时候才会生成)klass模型或者说元空间模型oop模型一个char数组对应一个TypeArrayKlass(TypeArrayKlass是c++的类)一个char数组对象对应一个typeArrayOopDeschsdb工具查看类的元信息(c原创 2022-02-23 22:36:46 · 1101 阅读 · 0 评论 -
jvm内存模型2
方法区方法区与元空间与永久代的关系方法区可以理解为是一个规范而永久代与元空间实现了这个规范永久代与元空间的区别永久代是jdk8之前的方法区的实现 它的数据存放在jvm的堆中用于存放类的原信息及instanceKlass类型的实例元空间jdk8之后方法区的实现 数据存放在直接内存(直接内存是java进程中的堆下面看一张图)代码段、数据区、栈都是操作系统层面的我们无法控制 只能控制运行时数据区中的东西运行时数据区又分为 下面的五部分由元空间实现的方法区是跟运行时数据区平级的也就是在直接内存中原创 2022-02-21 22:52:07 · 279 阅读 · 0 评论 -
Spring注解@RequestMapping
可以把类注册为bean的注解@component 把普通pojo实例化到spring容器中@controller 控制器(注入服务)@service 服务(注入dao)@repository dao(实现dao访问)增强bean的注解@RequestMapping指定访问路径 需要搭配@controller使用 如果只有@controller就没有请求路径 如果只有@RequestMapping注解在找调用链的时候会找不着可以成为bean的只能是component类型在这写死的只能识别c原创 2022-02-19 23:22:37 · 799 阅读 · 0 评论 -
解析java字节码
java字节码划分区域图中u4、u2等表示的是字节u4就是4个字节u2就是2个字节idea查看class的十六进制 看这里 https://blog.csdn.net/weixin_45112292/article/details/115609491其中魔术就是magic它表示的是字节码的开头CAFEBABE这个单词然后次版本号也就是minor version然后主版本号majorversion然后常量池。。。现在应该会看图了后面的不写了对应的次版本号与主版本号然后常量池类型图 先原创 2022-02-18 23:53:44 · 1261 阅读 · 0 评论 -
类的加载器二
类加载器在内存中的存储结构启动类加载器启动类加载器没有实体它是在一段逻辑称为启动类加载器这段逻辑做的事情是:加载类sun.launcher.LauncherHelper,执行该类的方法checkAndLoadMain反射底层原理反射底层存储的时候使用的字典dictionary 就是一个key:value类型的数据结构 可以搜索在openjdk8代码中搜SystemDictionary::find java的反射就会调用这个find方法 反射大体存储样子key是一个全类名加类加载器名算出的一个哈希值原创 2022-02-16 23:40:37 · 214 阅读 · 0 评论 -
Klass模型与类加载的详细机制
klass模型是jvm中的数据类型 这个数据类型表示的是一个java类 java语言是在jvm中运行而jvm是不认识java代码的我们使用javac编译的class文件jvm是不认识的 所以有一个类加载的动作 这个动作就是把class字节码拼装成一个klass类型 这个klass类型是c++中的一个类 klass里面有java类中的所有信息比如它的属性 方法 修饰符等成为类的元信息 这些信息放在元空间中 通过下面的klass类的继承关系图可以看出metaspace中文意思就是元空间 meatadata原创 2022-02-15 23:05:49 · 1677 阅读 · 1 评论 -
JNI简单理解使用
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar原创 2022-02-02 10:26:00 · 203 阅读 · 0 评论 -
c++(一)
与C语言的关系c++其实是为了蹭C语言的热度。但是现在很多人认为是C语言的Plus Plus版本。其实这样理解也说得过去。但是这个Plus的意思不是说对C语言的语法进行扩充,而是编译器在编译时做了更多事情。所以学会C++的核心不是学会它的语法,而是深刻理解编译器做了哪些事情,让C语言变成了C++。c++面向对象编程的语法封装struct Student { int age; int level; int print_age(); int print_level原创 2022-01-21 22:02:50 · 195 阅读 · 0 评论 -
c语言(二)
指针int* i = 0x11223344;*有两个作用一个是用来定义指针 这个好理解就是上面的i一个是用来把变量的值当为内存地址根据这个内存地址去找它的值 这个是我测出来的现象 比如 int* i2 = *i;这个东西然后它就会报错 报错的原因就是*i这样写指针就会认为0x11223344是一个内存地址然是它不是然后就报错了 也不能说是报错 是这个内存地址不存在什么数据都没有 如果i的值是一个真实存在的内存地址(简称a)那么*i就会把a对应的那块内存区域中的数据返回给i2 专业词叫做解引原创 2022-01-20 16:05:41 · 502 阅读 · 0 评论 -
c语言(一)
c语言编译器gcc、g++ gcc是用来编译c语言的 g++是用来编译c++的c语言的数据类型基本数据类型 char 它的长度是1字节 short 它的长度是2字节 int 它的长度是4字节 long 它的长度是4字节 float 它的长度是4字节 double 它的长度是8字节非基本类型 结构体 数组 指针结构体定义定义结构体的时候,一般用char数组数组作为成员属性,元素个数写在后面,写在前面会报错 struct原创 2022-01-18 22:23:45 · 381 阅读 · 0 评论 -
汇编语言(三)
esp是栈帧的栈顶 edp是栈帧中的栈低edp寻址就是寻找调用者中的数据esp寻址当使用push这个指令的时候它会进行这样 esp+数据的大小 然后得出的结果就是栈顶的内存地址 栈帧 然后push一个寄存器 会把当前寄存器中的数据保存到内存中 可以利用这个机制 做方法的调用 如果调用方法了 就先把edp的地址push一下 然后把esp赋值给edp这个就会形成一块内存空间 就是一个栈帧的形式 如果edp+数据大小就可以找到i的值 如果用esp加数据的大小就可以找到vv方法中变量的数据 这个过原创 2022-01-16 22:41:50 · 474 阅读 · 0 评论 -
汇编语言(二)
寄存器是cpu每个核都有的不会存在线程安全问题栈线程是基于栈去运行的windows、linux的内存地址内存地址是从大向小去使用的 原有的数据不会被覆盖 会在下次使用是进行覆盖从大到小就是一个先入后出的画面前面的依赖后面的用来存储内存地址的寄存器esp栈寄存器 存储当前线程的栈顶的内存地址 可以用来存放局部变量ebp栈低寄存器 可以用来存储入参数据宽度字节Byte: 八个比特 (Bit) 称为一个字节,是计算机中数据处理的基本单位字Word: 两个字节称为一个字双字Dwor原创 2022-01-15 23:11:00 · 99 阅读 · 0 评论 -
汇编常用指令
常用的汇编指令MOV:传送字或字节。 mov 寄存器名字比如rax 数值 // 这样写就可以对rax赋值了ADD: 加法。add 寄存器名字比如rax 数值 // 这样写就可以把数值赋值给rax了MOVSX 先符号扩展,再传送. MOVZX先零扩展,再传送. PUSH 把字压入堆栈.POP把字弹出堆栈. PUSHA把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈. POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出原创 2022-01-15 21:58:14 · 1616 阅读 · 0 评论 -
汇编语言(一)
汇编语言介绍可以说计算机是一堆由二进制数组成的在计算机刚出世的时候使用二进制写程序 打孔卡 原理就是一张纸你提前知道要在那打孔 通过打没打孔来表示数字(详细的自行百度)然后由于打孔机很麻烦 如果一个东西很繁琐那么就不会有人去做因为门槛太高就赚不了钱所以就出现了硬编码 硬编码就是把打孔卡封装了一层 把二进制数封装为十六进制(目前默认十六进制)比如1000 使用打孔卡就要写1010封装了一层就变成了8这样的一个效果 然后这样还是很麻烦就出现了汇编 汇编就是把十六进制数据封装成了英语单词比如add eax,原创 2022-01-15 00:17:18 · 394 阅读 · 0 评论 -
Kubernetes(K8S)二
K8S核心概念k8s有很多核心概念 先写几个DeploymentDeployment负责创建和更新应用程序的实例 创建Deployment后k8s master将应用程序实例调度到集群中的各个节点上,如果托管实例的节点关闭或被删除,Deployment控制器会将该实例替换为集群中另一个节点上的实例。这提供了一种自我修复机制来解决机器故障维护问题 白话就是之前用docker能在单机下载应用程序 运行应用程序 这个Deployment就是用来管理一下docker的这套机制 比如现在有机器a机器b两台机器原创 2022-01-12 20:50:20 · 890 阅读 · 0 评论 -
Kubernetes(K8S)一
K8S之前写了docker发现 docker只能在单机部署 docker部署分布式系统还是很麻烦 所以就有了K8S K8S全称Kubernetes(读音 库波奈第丝)可以把K8S理解为一个在docker基础上进一步封装 让docker可以支持部署分布式系统 当然docker也有自己实现的用来部署分布式系统的工具 docker-swarm只不过docker-swarm被k8s打败了 k8s是一个管理docker的工具实现了自动化运维管理多个跨机器 Docker 程序的集群K8S核心特性服务发现与负载均原创 2022-01-12 00:36:52 · 2337 阅读 · 0 评论 -
Prometheus&Grafana
Prometheus是一个全能选手 原生支持容器监控 也支持传统应用程序 它具备所有监控系统都具备的流程 数据采集 --》数据处理 --》数据存储 --》数据展示 --》警告prometheus中文名字普罗米修斯最初在soundCloud上构建的监控系统,自2012年称为社区开源项目 用户非常活跃的开发人员和用户社区2016年加入cncf称为继kubernetes之后的第二个托管项目 官方地址https://prometheus.io/Prometheus 特点展开目录多维数据模型:由度量名称和键原创 2022-01-10 23:19:33 · 641 阅读 · 0 评论 -
Docker Compose
Docker Compose介绍使用微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例。如果每个微服务都要手动启停,那么效率之低、维护量之大可想而知。而Docker Compose可以变的很轻松、高效地管理容器。为了简单起见将 Docker Compose简称为 Compose。Compose 是一个用于定义和运行多容器的Docker应用的工具。使用Compose,你可以在一个配置文件(yaml格式)中配置你应用的服务,然后使用一个命令,即可创建并启动配置中引用的所有服务。Doc原创 2022-01-08 22:52:14 · 96 阅读 · 0 评论 -
Docker二
将微服务运行在docker上使用Dockerfile构建Docker镜像Dockerfile是一个文本文件,其中包含了若干条指令,指令描述了构建镜像的细节先来编写一个最简单的Dockerfile,以前文下载的Nginx镜像为例,来编写一个Dockerfile修改该Nginx镜像的首页1、新建一个空文件夹docker-demo,在里面再新建文件夹app,在app目录下新建一个名为Dockerfile的文件,在里面增加如下内容:FROM nginxRUN echo '<h1>This i原创 2022-01-07 21:43:17 · 1544 阅读 · 0 评论 -
Docker一
DockerDocker是一个开源的容器引擎,它有助于更快地交付应用。Docker可以将应用程序和基础设施(比如mysql、mq)层进行隔离 并且能将基础设施当做程序一样进行管理 使用Docker可以更快的打包、测试以及部署应用程序,并可以缩短从编写到部署运行代码的周期Docker就跟maven一样 maven只是把java的依赖jar放到了maven仓库中 我们使用什么jar直接从maven仓库中下载 而Docker是把所有运行环境继承到Docker的仓库 当我们需要jdk、mq、Tomcat时只需要原创 2022-01-06 23:10:41 · 266 阅读 · 0 评论 -
面向领域编程DDD二
ddd的思想就是 把业务的实现抽离出去 根据mvc的思想是一层controller用来接收用户请求 一层service用来处理业务逻辑 在service这一层实现代码是根据开发人员经验进行编写 这样就会造成业务的实现要另一个人看懂会很麻烦 不熟悉开发的人员看就更难了 而ddd的思想就是把业务实现抽离出来 可以在改动实现的时候不用更改service层里的代码 ddd的四层架构 用户接口层、应用层、领域层、基础数据层用户接口层就是用来接收请求的就是controller层应用层就是业务的实现就是service原创 2022-01-05 22:46:57 · 875 阅读 · 0 评论 -
面向领域编程ddd一
public class PaymentController{private PayService payService;public Result pay(String merchantAccount,BigDecimal amount){Long userId = (Long) session.getAttribute(“userId”);return payService.pay(userId, merchantAccount, amount);}}public class PaySer原创 2022-01-04 21:44:50 · 673 阅读 · 1 评论 -
中台的介绍
中台 是国内互联网中 继微服务又一个火热的概念,从2015年阿里提出小前台+大中台的概念后 中台成了国内微服务实施过程中绕不开的一个目标 虽然中台的实施如火如荼 但是关于中台依然是 雾里看花 一百个人会有一百中理解所谓中台 就是将各个业务线中可以复用的一些功能抽取出来,剥离个性,提取共性,形成一些可复用的组件,通过这些组件,就可以使日后的系统开发成本降低,质量提高 大体上中台可以分为三类,业务中台,数据中台和技术中台业务中台就是抽象出来,在各个业务线都可以共用的一些业务组件 像用户权限、会员管理、移动支原创 2022-01-03 22:19:25 · 2863 阅读 · 0 评论