JVM 虚拟机原理、Java 代码优化、秒杀系统
JVM虚拟机原理
JVM组成架构
Java是一种跨平台的语言,JVM屏蔽了底层系统的不同,为Java字节码文件构造了一个统一的运行环境。
Java 字节码文件
Java 如何实现在不同操作系统、不同硬件平台上,都可以不用修改代码就能顺畅地执行?
计算机领域的任何问题都可以通过增加个中间层(虚拟层)来解决
Java所有的指令有200个左右,一个字节(8位)可以存储256种不同的指令信息,一个这样的字节称为字节码(Bytecode)。在代码的执行过中,JVM将字节码解释执行屏蔽对底层操作系统的依赖,JVM也可以将字节码编译执行,如果是热点代码,会通过JIT动态地编译为机器码,提高执行效率。
字节码执行流程
Java字节码文件编译过程
类加载器的双亲委托模型
低层次的当前类加载器,不能覆盖更高层次类加载器已经加载的类。如果低层次的类加载器想加载一个未知类,需要上级类加载器确认,只有当上级类加载器没有加载过这个类,也允许加载的时候,才让当前类加载器加载这个未知类。
自定义类加载器
- 隔离加载类:同一个JVM中不同组件加载同一个类的不同版本。
- 扩展加载源:从网络、数据库等处加载字节码。
- 字节码加密:加载自定义的加密字节码,在ClassLoader中解密。
堆&栈
- 堆:每个JVM实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享。
- 堆栈:JVM为每个新创建的线程都分配一个堆栈。也就是说,对于一个 Java程序来说,它的运行就是通过对堆栈的操作来完成的。
Java 中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的引用而已。
方法区&程序计数器
方法区主要存放从磁盘加载进来的类字节码,而在程序运行过程中创建的类实例则存放在堆里。程序运行的时候,实际上是以线程为单位运行的,当JVM进入启动类的main方法的时候,就会为应用程序创建一个主线程,main方法里的代码就会被这个主线程执行,每个线程有自己的Java栈,栈里存放着方法运行期的局部变量。而当前线程执行到哪一行字节码指令,这个信息则被存放在程序计数寄存器。
package com.bjsxt.test;public class Demo01 { public static void main(String[] args) A a = new A(); System.out.println(A.width); }}class A { public static int width=100; static{ System.out.println("静态初始化类A"); width=300; } public A(){ System.out.println("创建A类的对象"); }}
Java(线程)栈
所有在方法内定义的基本类型变量,都会被每个运行这个方法的线程放入自己的栈中,线程的栈彼此隔离,所以这些变量一定是线程安全的。
线程工作内存 & volatile
Java内存模型规定在多线程情况下,线程操作主内存变量,需要通过线程独有的工作内存拷贝主内存变量副本来进行。
一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
- 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
- 禁止进行指令重排序。
Java运行环境
JVM的垃圾回收
JVM垃圾回收就是将JVM堆中的已经不再被使用的对象清理掉,释放宝贵的内存资源。
JVM通过一种可达性分析算法进行垃圾对象的识别,具体过程是:从线程栈帧中的局部变量,或者是方法区的静态变量出发,将这些变量引用的对象进行标记,然后看这些被标记的对象是否引用了其他对象,继续进行标记,所有被标记过的对象都是被使用的对象,而那些没有被标记的对象就是可回收的垃圾对象了。
进行完标记以后,JVM就会对垃圾对象占用的内存进行回收,回收主要有三种方法
- 清理:将垃圾对象占据的内存清理掉,其实JVM并不会真的将这些垃圾内存进行清理,而是将这些垃圾对象占用的内存空间标记为空闲,记录在一个空闲列表里,当应用程序需要创建新对象的时候,就从空闲列表中找一段空闲内存分配给这个新对象。
- 压缩:从堆空间的头部开始,将存活的对象拷贝放在一段连续的内存空间中,那么其余的空间就是连续的空闲空间。
- 复制:将堆空间分成两部分,只在其中一部分创建对象,当这个部分空间用完的时候,将标记过的可用对象复制到另一个空间中。
JVM分代垃圾回收
JVM垃圾回收器算法
G1垃圾回收内存管理机制
-XX:MaxGCPauseMillis
Java启动参数
标准参数,所有的JVM实现都必须实现这些参数的功能,而且向后兼容
- 运行模式-server,-client
- 类加载路径-cp,-classpath
- 运行调试--verbose
- 系统变量--D
非标准参数,默认jvm实现这些参数,但不保证所有jvm实现都实现,且不保证向后兼容
·-Xms初始堆大小
·-Xmx最大堆大小
·-Xmn新生代大小
·-Xss线程堆栈大小
非Stable参数,此类参数各个jvm实现会有所不同,将来可能会随时取消
·-XX:-UseConcMarkSweepGC 启用CMS垃圾回收
JVM 性能诊断工具
基本工具:JPS,JSTAT,JMAF
集成工具:JConsole,JVisualVM
JPS
JPS 用来查看 host 上运行的所有 java 进程的 pid (jvmid),一般情况下使用这个工具的目的只是为了找出运行的jvm进程ID,即lvmid,然后可以进一步使用其它的工具来监控和分析JVM。
常用的几个参数:
- -l 输出java应用程序的main class的完整包
- -q 仅显示pid,不显示其它任何相关信息
- -m 输出传递给main方法的参数
- -v 输出传递给JVM的参数。在诊断JVM相关问题的时候,这个参数可以查看JVM相关参数的设置
JSTAT
JSTAT("Java Virtual Machine statistics monitoring tool")是JDK自带的一个轻量级小工具。主要对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。
语法结构如下:jstat [Options] vmid [interval] [count]
- Options -- 选项,我们一般使用 - gcutil查看gc情况
- vmid -- VM的进程号,即当前运行的java进程号
- interval -- 间隔时间,单位为毫秒
- count -- 打印次数,如果缺省则打印无数次
S0 -- Heap上的 Survivor space 0 区已使用空间的百分比
S1 -- Heap上的 Survivor space 1区已使用空间的百分比
E -- Heap上的 Eden space 区已使用空间的百分比
O -- Heap上的 Old space 区已使用空间的百分比
YGC -- 从应用程序启动到采样时发生 Young GC 的次数
YGCT -- 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC -- 从应用程序启动到采样时发生 Full GC 的次数
FGCT -- 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT -- 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
JMAP
JMAP是一个可以输出所有内存中对象的工具,甚至可以将VM中的heap,以二进制输出成文本。
使用方法
- jmap-histo pid>a.log可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。
- jmap-dump:format=b,file=f1 PID可以将该PID进程的内存heap输出出来到f1文件里。
JConsole
JVisualVM
Java代码优化
合理并谨慎使用多线程
使用场景(1/0阻塞,多CPU并发)
资源争用与同步问题
java.util.concurrent
启动线程数=[任务执行时间/(任务执行时间−IO等待时间)]∗CPU内核数
- 最佳启动线程数和CPU内核数量成正比,和IO阻塞时间成反比。如果任务都是CPU计算型任务,那么线程数最多不超过CPU内核数,因为启动再多线程,CPU也来不及调度;相反如果是任务需要等待磁盘操作,网络响应,那么多启动线程有助于提高任务并发度,提高系统吞吐能力,改善系统性能。
竞态条件与临界区
在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。
当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞态条件发生的代码区称作临界区。
在临界区中使用适当的同步就可以避免竞态条件。
Java线程安全
允许被多个线程安全执行的代码称作线程安全的代码。
局部变量
- 局部变量存储在线程自己的栈中。也就是说,局部变量永远也不会被多个线程共享。所以,基础类型的局部变量是线程安全的。
局部的对象引用
- 如果在某个方法中创建的对象不会逃逸出该方法,那么它就是线程安全的。
对象成员
- 对象成员存储在堆上。如果两个线程同时更新同一个对象的同一个成员,那这个代码就不是线程安全的。
Java Web应用的多线程从哪儿来的?
- 来自于容器
Servlet是线程安全的吗?
- 不安全。Servlet是单实例的,所有的用户请求线程访问的是同一个Servlet,而Servlet里的成员变量就有可能被多线程同时修改、同时访问到。
- 安全。一个Servlet安全不安全,Servlet本身是不知道的,你有多线程共享的变量你就是不安全的,没有共享变量的话就是安全的。Servlet本身是安全的,但是你写了一个不安全的类就会导致它不安全。
ThreadLocal
创建一个 Threadloca|变量
- private ThreadLocal myThreadLocal = new ThreadLocal();
存储此对象的值
- myThreadLocal.set("A thread local value");
读取一个 Threadlocal对象的值:
- String threadLocalValue=(String) myThreadLocal.get();
public void set(T value){ Thread t = Thread.currentThread(); ThreadLocalMap map=getMap(t); if (map != null) map.set(this,value); else createMap(t,value);}void createMap (Thread t, T firstValue) { t.threadlocals=new ThreadLocalMap(this,firstValue);}
Java内存泄漏
Java内存泄漏是由于开发人员的错误引起的。
如果程序保留对永远不再使用的对象的引用,这些对象将会占用并耗尽内存。
- 长生命周期对象
- 静态容器
- 缓存
合理使用线程池和对象池
- 复用线程或对象资源,避免在程序的生命期中创建和删除大量对象
- 池管理算法(记录哪些对象是空闲的,哪些对象正在使用)
- 对象内容清除(ThreadLocal的清空)
使用合适的JDK容器类(顺序表,链表,Hash)
- LinkList和ArrayList的区别及适用场景
- HashMap的算法实现及应用场景
- 使用concurrent包,ConcurrentHashMap和HashMap的线程安全特性有什么不同?
缩短对象生命周期,加速垃圾回收
- 减少对象驻留内存的时间
- 在使用时创建对象,用完释放
- 创建对象的步骤(静态代码段-静态变量-父类构造函数-子类构造函数)
使用I/O buffer及NIO
- 延迟写与提前读策略
- 异步无阻塞IO通信
优先使用组合代替继承
- 减少对象藕合
- 避免太深的继承层次带来的对象创建性能损失
合理使用单例模式
- 无状态对象
- 线程安全
虚拟化所有层次
- 计算机的任何问题都可以通过间接层解决
- 一致性hash算法的虚拟化实现
- 面向接口编程
- 7层网络协议
秒杀
XXXX 性能现状
XXXX网站的正常流量情况
- 并发(单台),高峰期<10;
- 吞吐量(TPS,单台)高峰期,<60;
- CPU负载Load高峰期,<2,大部分服务器<1;
- CPU使用率,一般只占1颗核,平均60%左右;
- 服务器平均响应时间高峰期,<150ms;
- 图片总流量带宽1.8G(各网站总合)。
高并发下的风险
- 网络带宽耗尽
- 服务器Load飘高,停止响应。
- 数据库瘫疾
高并发下的事故
- 事故:网站运营推广页面弹出1兆大图片导致带宽耗尽
- 增加审核机制:运营推广增加的图片流量不能超过现有流量的30%
- 合作媒体推广:迅雷,暴风影音浮出广告,导致ZZ集群Crash。
秒杀
- XXXX.com开业88小时不间断秒杀活动
高并发对网站性能的影响
- 并发数对吞吐量的影响
- 并发数对用户平均请求等待时间的影响
- 并发数对服务器平均请求响应时间的影响
高并发实例:XXXX.com开业秒杀活动
商业需求
- 为庆祝XXXX.com开业推出88小时不间断秒杀活动。
- 每小时整点推出8款商品......
- 每款商品供168件,每人限批3件,成交人数56人。
- CCTV黄金广告时间,各种网络,平面媒体轰炸,总广告费:1.5亿。
- 接到运营通知,距秒杀开始仅仅5天时间。
技术挑战
- 瞬间高并发
- 8000并发:预估秒杀在线人数可达8000人。
- 风险:带宽耗尽。
- 服务器:崩溃,可以理解成自己给自己准备的D.D.O.S攻击。
- 秒杀器
- 第一种:秒杀前不断刷新秒杀页面,直到秒杀开始,抢着下单。
- 第二种:跳过秒杀页面,直接进入下单页面,下单。
XXXX.com 秒杀系统:服务器和网络准备
服务器准备(距秒杀开始仅五天时间来不及采购)
- style服务器(Lighttpd集群):5台
- 图片服务器(Nginx集群):5台
- 静态服务器(Apache集群):10台
- 交易服务器(JBoss动态集群):10台
带宽准备
- 图片出口带宽上限:2.5G(出口带宽支持10G,但图片服务器集群的处理能力:图片服务集群最大并发处理能力 * 网站平均图片大小=2.5G)
- CDN准备:Chinacache沟通;借用CCCC CDN
XXXX.com 秒杀系统:架构目标
1.图片网络带宽:1.0G
新增图片带宽:必须控制在1.0G左右
每件商品秒杀页面的图片总大小不得超过:1000000/(1000*8)=125K/每商品
2.网站并发:
单件商品并发:1000【来自运营的预估】
总并发:8(件商品)*1000(人/商品)=8000
XXXX秒杀系统:组成
简单系统:
三个页面组成:秒杀商品列表,秒杀商品介绍,下单
XXXX.com 秒杀系统:设计原则
静态化
- 采用JS自动更新技术将动态页面转化为静态页面
并发控制,防秒杀器
- 设置阀门,只放最前面的一部分人进入秒杀系统
简化流程
- 砍掉不重要的分支流程,如下单页面的所有数据库查询
- 以下单成功作为秒杀成功标志。支付流程只要在1天内完成即可。
前端优化
- 采用YSLOW原则提升页面响应速度
XXXX秒杀系统:静态化(1)
秒杀商品list和Detail是静态HTML页面
XXXX秒杀系统:静态化(2)
秒杀商品列表/秒杀商品介绍页面,如何判断秒杀开始否。
答案:valid-offer.js
var valid_offerIds=23624364,53778658,35885833,46999696,5006797057
三道阀门的设计
阀门:基于TT的计数器
秒杀器的预防
秒杀 Detail 页面
- URL:随机
- 秒杀前2秒放出,脚本生成,秒杀前。
- 1000次访问上限控制【每件商品只能放入1000人浏览】。
下单页面:
- 订单ID,随机。
- 不能直接跳过秒杀Detail页面进入。
- 每个秒杀商品,带预先生成的随机Token作URL参数。
- 如果秒杀过,直接跳到秒杀结束页面。
- 100次访问上限控制【每件商品只能放入100人下单】。
Web Server 调优-Apache调优
- KeepAlive 相关参数调优
- 其他参数调优
- HostnameLookups设为off,对allowfromdomain等后的域名不进行正向和反向的dns解析。
- 关闭cookies-log日志
- 打开 Linux sendfile()
- 关闭无用的module
- mod_Gzip
- (秒杀页面,非图片HTML文本所占流量比重可忽略不计,zip意义不大)
- mod_Beacon
- mod_hummock(等待反应过来,秒杀已经over了)
Web Server 调优-JBoss调优
Mod-jk worker 调优
JkWorkerProperty worker.list=localnodeJkWorkerProperty worker.localnode.port=7011JkworkerProperty worker.localnode.host=localhostJkWorkerProperty worker.localnode.type=ajp13JkWorkerProperty worker.localnode.ibfactor=1 JkWorkerProperty worker.localnode.socket_keepalive=TrueJkWorkerProperty worker.localnode.socket_timeout=20JkWorkerProperty worker.localnode.connection_pool_minsize=25JkWorkerProperty worker.localnode.connection_pool_timeout=600
JBoss AJP Connector
Tomcat APR 设定
秒杀静态页面优化
图片合并
- 8张图片合并成1张,CSS偏移展示。
- 减少HTTP请求数,减少请求等待数。
- 减少发送Cookies的量。
HTML内容压缩
图片压缩:图片 Bytes < 长*宽/2250
HTML Header Cache-Control 设置
CSS, JS精简
- CSS,JS精简到极致,部分直接写在页面中,减少HTTP请求次数。
下单页面优化
数据库操作:全部砍掉
- 原下单页面要访问8次数据库,全部砍掉。
秒杀流程精简
- 砍掉填写或选择收货地址,放在秒杀成功后填写。
- 砍掉调用是否开通支付接口,秒杀首页文案提示必须开通。
采用内存缓存
- 秒杀Offer数据,支付相关信息,缓存。
交易系统性能优化
- 交易系统调优目标:
- 关闭KeepAlive(分析交易系统 accesslog,用户在短时间内连续点击概率很低)
- JVM优化
- 优化CMS垃圾回收器的参数
- 消灭Top10Bottlenecks
- Velocity参数调优
- 采用DBCP1.4替换C3P0
- Offer产品参数的XML解析
二跳页面的优化
XXXX.com其他页面
- 前端优化:Yslow规则调优
- 减少HTTP请求,合并JS,CSS,图片,充分利用浏览器缓存。
- 图片压缩,公式: 图片 Bytes < 长*宽/2250
- 避免发送Cookies
交易系统优化
- 普通订单管理列表和XXXX秒批订单管理列表分离
- 禁止用模糊查询功能
应急预案
- 域名分离,独立域名,不影响XXXX原有业务。
>Style集群:style.XXXX.china.XXXX.com
>图片服务器集群:img.XXXX.china.XXXX.com
>静态页面集群:page.XXXX.china.XXXX.com
>出问题直接把XXXX相关域名卡掉,所有请求跳到万能出错页面。
- 机动服务器10台,备用。
- 拆东培补西墙战略
>5天时间来不及采购服务器,因此SA待命,随时准备将非核心应用集群的兄余服务器下线,加入到秒杀集群。
- 壁虎断尾策略
>所有办法均失效的情况下,例如流量耗尽。
>非核心应用集群统统停止服务,如资讯,论坛,博客等社区系统。
>保住首页,Offer Detail,旺铺页面等核心应用的可用性。
- 万能出错页面:秒杀活动已经结束
>任何出错都302跳转到此页面
>位于另外集群
- 万幸:最终所有的预案都没有用上
秒杀活动结果
88小时秒杀,坚守阵地,大获成功。
秒杀还是被秒杀?终于有了答案
三道阀门设计非常有效,拦住了秒杀器。
- XXXX.com 静态集群总并发情况(首页,秒杀列表,秒杀商品页面)
- 交易系统集群总并发情况(下单页面)
改进一:采用更轻量/快速的服务器(1)
采用 Lighttpd 替代 Apache 杀手铜(AIO)
Lighttpd 1.5 VS Apache2.2.4
小页面性能(100K)
- http_load-verbose-timeout 40-parallel 100-fetches 500 http-load.10M.urls-100M
大页面性能(10M)
性能关键:Web Server的高性能I/O
XXXX应用服务器升级项目:
Apache2.2+Mod-Proxy+Jetty7.1.5 与XXXX现有架构性能对比:
性能大幅提升,XXXX全站下线1/3应用服务器(100台,明年不用采购新机器)
架构更轻量,配置更简单
应用更无状态化,开发和维护的福音
更加安全
改进二:前端优化自动化
- XXXX服务器响应时间<150ms,但Offer Detail 页面用户等待时间5s,大部分时间耗在路上(资源请求和网络传输)
- 图片自动压缩(CMS自动压缩)
- Cookies服务化(控制Cookies的大小)
- XXXX前端延迟加载框架SmartLoad(只加载首屏数据)
- Google mod pagespeed module
- 自动压缩图片,静态资源,智能浏览器缓存技术
- Google Diffable(增量下载静态资源技术)
改进三:架设镜像站组建山寨CDN
XXXX 青岛镜像站项目
改进四:采用反向代理加速核心页面
在Offer集群前部署 Squid反向代理集群
- Offer Detail的Squid反向代理改造
- 基于消息的Squid缓存更新机制
改进五:海量数据的透明垂直切分
XXXX 性能优化领域立项中
搜索引擎
- 互联网搜索引擎整体架构
- 爬虫系统架构
- 爬虫禁爬协议
- User-agent: GoogleBot
- Disallow: /tmp/
- Disallow: /cgi-bin/
- Disallow: /users/paranoid/
- 文档矩阵与倒排索引
- 文档与倒排索引
- 带词频的倒排索引
- 带词频与位置的倒排索引
- Lucene架构
- Lucene倒排索引
- Lucene索引文件准实时更新
- 索引有更新,需重新全量创建一个索引来替换原来的索引,这种方式在数据量大时效率很低,并且由于创建一次索引的成本很高,性能也很差
- Lucene中引入了段的概念,将一个索引文件拆分为多个子文件,每个子文件叫做段,每个段都是一个独立的可被搜索的数据集,索引的修改针对段进行操作
- 新增:新数据需要创建索引,选择新建一个段来存储新增的数据
- 删除:当需要删除数据时,在索引文件新增一个.del的文件,用来专门存储被删除的数据ID
- 更新:是删除与新增的组合
- 为了控制索引里段的数量,必须定期进行段合并操作
- ElasticSearch架构
(Lucene缺点是不支持分布式,数据量很大时考虑ElasticSearch)
- 索引分片,实现分布式
- 索引备份,实现高可用
- API更简单、更高级
- ES分片预分配与集群扩容
- shard = hash(routing)%number_of_primary_shards
- 网页排名算法 PageRank
PageRank,网页排名,又称网页级别,Google左侧排名或佩奇排名,是一种由搜索引擎根据网页之间相互的超链接计算的技,而作为网页排名的要素之一,以Google公司创辨人拉里·佩奇(Larry Page)之姓來命名。
- PageRank 让链接来 [投票]
PageRank通过网络浩瀚的超链接開像来确定一个页面的等级。Google把从A页面到B页面的链接解释为A页面给B页面投票,Google根据投票来源(甚至来源的来源,即链接到A页面的页面)和投票目标的等级来决定新的等级。简单的说,一个高等级的页面可以使其他低等级页面的等级提升。
一个页面的「得票数」由所有链向它的页面的重要性来决定,到一个页面的超链接相当于对该页投一票。一个页面的PageRank是由所有链向它的页面([链入页面])的重要性经过递归算法得到的。一个有较多链入的页面会有较高的等级,相反如果一个页面没有任何链入页面,那么它没有等级。
- PageRank算法
假设一个由4个页面组成的小团体:A,B,C和D。如果所有页面都链向A,那么A的PR(PageRank)值将是B,C及D的Pagerank总和。
PR(A)=PR(B)+PR(C)+PR(D)
JVM 虚拟机原理、Java 代码优化、秒杀系统相关推荐
- 深入JVM虚拟机(四) Java GC收集器
转载自 深入JVM虚拟机(四) Java GC收集器 1 GC收集器 1.1 Serial串行收集器 串行收集器主要有两个特点:第一,它仅仅使用单线程进行垃圾回收:第二,它独占式的垃圾回收. 在串行 ...
- JVM优化原理—Java架构师必须要知晓的知识
想要成为一名出色的Java架构师,必须要彻底了解Java的一个重要的特点那就JVM ...
- java虚拟机原理(java虚拟机的基本结构)
虚拟机的分类 虚拟机大体上分为系统虚拟机和程序虚拟机: 如:大名鼎鼎的VMware就属于系统虚拟机,VMware是完全对物理计算机的仿真,提供一个可以运行完整操作系统的软件平台: 程序虚拟机的代表就是 ...
- Redis队列实现Java版秒杀系统(无脚本、可用于生产)
本文系转载,原作者:控场的朴哥 原文地址:blog.csdn.net/weixin_43074462/article/details/103756536 写在前面 需求是做一个秒杀系统,比如大家来抢1 ...
- Redis 队列实现Java版秒杀系统(无脚本、可用于生产)
写在前面 需求是做一个秒杀系统,比如大家来抢100台手机,先到先得. 查阅了网上很多用redis实现秒杀的demo(java语言),竟然没一个能用的!!! 有些是php的,没闲心研究了,现在说说为什么 ...
- 2019最新 Java商城秒杀系统的设计与实战视频教程(SpringBoot版)
第一章 1-1课程整体介绍.mp4 1-2核心技术列表.mp4 1-3课程要求与收益.mp4 1-4系统的整体演示.mp4 https://www.jianshu.com/writer#/notebo ...
- JVM虚拟机原理深入解析,聪明人已经收藏了!
前文 本文希望通过揭开一些 React 隐藏的技术细节, 来辅助对官方文档中某些概念的理解 读者可以将本文看做对官方文档的补充 行文方式我采用的是提问-解答的方式, 即先根据官方文档给出的使用规则, ...
- java转换成class文件_浅谈JVM编译原理-.java文件转变为.class文件的过程
为什么需要编译? 我们平常写代码,有规范的命名方式,都能够看得懂,但是我们写的代码计算机是看不懂的,所以需要编译,也就是一个转换的过程,如下: 1.这个是咱们平时写的代码,就比较好理解,对人友好 2. ...
- 编译原理代码生成器java_浅谈JVM编译原理-.java文件转变为.class文件的过程
为什么需要编译? 我们平常写代码,有规范的命名方式,都能够看得懂,但是我们写的代码计算机是看不懂的,所以需要编译,也就是一个转换的过程,如下: 1.这个是咱们平时写的代码,就比较好理解,对人友好 2. ...
最新文章
- html5搜索框美化,CSS美化的漂亮搜索框
- savexml php,PHP DOMDocument saveXML()用法及代码示例
- shell 判断字符串相等_编程小短文:Bash子字符串还在用==?试试=~性能瞬间飙升100倍...
- php报错提醒,php报错问题
- 句句真研—每日长难句打卡Day15
- 基础集群部署 - kubernetes-simple
- 笑傲江湖与三层交换、路由......
- STM32+L298N+PWM可调速小车(四驱)
- 子网掩码计算java,JAVA获取子网掩码源代码
- maven-replacer-plugin的使用
- Oracle 数据库表空间容量调整(表空间缩容脚本)脚本
- 数据驱动故障诊断方法汇总
- 【待更新】【UWB】UWB 学习、使用及 QCA平台移植实例
- 华为路由器旁挂引流实验(使用流策略)
- python计算长方体体积代码_编写程序,计算一个长方体的表面积和体积。
- 目标检测One-stage和Two-stage的区别
- 「Cpolar」看我如何实现公网远程控制Mac OS【使用mac自带VNC】
- 浏览器被劫持了 hao123
- 用计算机弹c哩c哩简谱数字,【扒谱】2020哔哩哔哩拜年祭部分数字谱
- Java单例破坏以及防止