目录 一、Java的运行路径二、编译原理三丶类加载机制装载:链接:(1)、验证(Verify):(2)、准备(Prepare)(3)、解析(Resolve) 初始化 四丶类加载器(classloader)加载原则(双亲委派)父类委托机制破坏双亲委派 五丶运行时数据区(Run-Time Data Areas)Method Area(方法区)Heap(堆)Stacks(虚拟机栈)栈针: The pc Register(程序计数器)Native Method Stacks(本地方法栈) 六丶栈,堆,方法区的指向栈指向堆方法区指向堆堆指向方法区 七丶jvm内存模型对象创建过程为什么需要Survivor区?只有Eden不行吗?为什么需要两个Survivor区?新生代中Eden:S1:S2为什么是8:1:1?堆内存中都是线程共享的区域吗? 八丶java对象内存模型九丶垃圾回收1丶如何确定一个对象是垃圾?引用计数法:可达性算法: 2丶什么时候会垃圾回收?四种GC条件满足其一: 3丶垃圾收集算法标记-清除标记:清除:缺点: 标记-复制标记-整理SerialSerial OldParNewParallel ScavengeParallel OldCMSG1(Garbage-First)ZGC 5丶垃圾收集器分类6丶常见问题吞吐量和停顿时间如何选择合适的垃圾收集器如何开启需要的垃圾收集器 十丶JVM参数标准参数-X参数-XX参数其他参数查看参数设置参数的常见方式实践和单位换算 十一丶内存内存溢出(OOM)内存泄露导致内存溢出 十二丶 JVM性能优化指南十三丶常见问题内存泄漏与内存溢出的区别young gc会有stw吗?major gc和full gc的区别什么是直接内存?垃圾判断的方式?不可达的对象一定要被回收吗?为什么要区分新生代和老年代?G1与CMS的区别是什么?方法区中的无用类回收 总结 一、Java的运行路径 java->class文件->jvm(虚拟机)->操作系统->硬件层面(010101的机器码)。
JVM各种折腾[内部结构、执行方式、垃圾回收、本地调用等]。
特点:一次编译到处运行
二、编译原理 Person.java -> 词法分析器 -> tokens流 -> 语法分析器 -> 语法树/抽象语法树。
-> 语义分析器 -> 注解抽象语法树 -> 字节码生成器 -> Person.class文件。
三丶类加载机制 装载: 查找和导入class文件
(1)通过一个类的全限定名获取定义此类的二进制字节流。
(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
(3)在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。
方法区和堆
Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。在 Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口 (对象不一定都在堆,对象可能在栈上分配)。
链接: (1)、验证(Verify): 保证被加载类的正确性(贯穿整个流程的过程,要用到的时候才会去验证)
文件格式验证
元数据验证
字节码验证
0x00 RSA简介 RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
0x01 RSA原理 原文连接
这次轮到RSA加密算法了。RSA加密过程相对DES和MD5要简单很多,但作为现在还在使用的加密算法之一,它还是有需要认真思索的地方哒~
首先是密钥对的生成:
(1)选取两个大素数p和q(目前两个数的长度都接近512bit是安全的)
(2)计算乘积n=p*q,Φ(n)=(p-1)(q-1),其中Φ(n)为n的欧拉函数(因为两素数乘积的欧拉函数等于两数分别减一后的乘积)
(3)随机选取整数e(1<e<Φ(n))作为公钥d,要求满足e与Φ(n)的最大公约数为1,即两者互素
(4)用Euclid扩展算法计算私钥d,已满足d * e ≡ 1 (mod Φ(n)),即d ≡ e^(-1) (mod
Φ(n))。则e与n是公钥,d是私钥
注意:e与n应公开,两个素数p和q不再需要,可销毁,但绝不可泄露。
加密过程:
将接收到的明文转换成特定的编码方式。如p=43,q=59,e=13,明文为cybergreatwall,按照英文字母表的顺序a=00,b=01,… ,z=25进行编码后为022401041706001922001111。
现在可以加密了~~ ci ≡ mi^e (mod n)
0x02 中国剩余定理(CRT) (abc)%n = ((a%n)(b%n)(c%n))%n
使用该定理可有效避免数值溢出。
0x03 C语言代码实现 #include <stdio.h> #include <string.h> //最大公约数。 int gcd(int x,int y){ if(y) return gcd(y, x%y); else return x; } //求e关于(p-1)(q-1)的逆元d:私钥 int extend(int e, int fhla){ for(int d=2; d<fhla; d++){ // 1<d<fhla if(e*d%fhla==1){ return d; } } } //加密 int c[100]; //用于存储密文 int len; void encrypt(int e, int n){ char plaintext[100]; printf("
SQL
–创建表
create table 表名(字段名 字段类型);
create table user(
id number,
name varcahr2(20),
sex vrachr2(1)
);
–删除表
drop table 表名;
drop table user;
–添加主键
alter table 表名 add constraint 约束名 primary key(id);
alter table user add constraint pk_user primary key(id);
–删除主键
alter table 表名 drop constraint 约束名;
alter table user drop constraint pk_user;
–创建一般索引
create index 索引名 on user(创建索引的字段);
create index in_user on user(name);
–创建唯一索引(主键oracle默认为其创建唯一索引)
create unique 索引名 on user(创建索引的字段);
之前写过一次博客 Matlab&Python 如何在figure上画出表格
这次是对该博客的优化
图的结果见下相对之前有很大的进步:
coding 在这里包含数据的绘制,表格的添加,设置表格的大小、位置等
clc clear close all; path(path,'E:\new_matlab_Tool\export_fig3.25\export_fig-master'); %% 表格数据 data_row1=[68,68,86,43]; data_row2=[48,15,37,25]; data=[data_row1;repmat(data_row2,12,1)]; %% 表格作图 fig_size = 800; figure('color','w','position',[0, 0, fig_size*1.414,fig_size]); plot( data(:,1), 'k-','LineWidth',1.2 ); hold on; plot( data(:,1), 'k.','MarkerSize',20); plot( data(:,2), 'b-','LineWidth',1.2 ); plot( data(:,2), 'b.','MarkerSize',20); plot( data(:,3), 'r-','LineWidth',1.2 ); plot( data(:,3), 'r.','MarkerSize',20); plot( data(:,4), 'g-','LineWidth',1.2 ); plot( data(:,4), 'g.','MarkerSize',20); %% 生成表格行列名称,m行n列 str1='气旋';str2='TC'; m=13;n=4; column_name=strcat(str1,num2str((1:n)')); row_name=strcat(str2,num2str((1:m)')); ut = uitable(gcf,'Data',data,'Position',[550 450 400 246], ... 'Columnname',column_name,'Rowname',row_name,'BackgroundColor',[0 0.
类型:数值运算
描述
大学第一学期必选课程及其学分如下:
Python高等数学大学英语大学体育军事理论哲学3学分4学分4学分2学分2学分2学分 请计算并输出大学第一学期共修多少学分?输入每学分应缴纳的学费(整数,单位为元),计算并输出第一学期应缴纳多少学费?输出格式请参考输入输出示例。
输入
输入一个表示每学分应缴纳的学费的整数
输出
按示例格式分两行输出学分和学费
示例
输入: 328 输出: 你本学期选修了17个学分。 你应缴纳的学费为5576元。 python = 3 math = 4 english = 4 physical = 2 military_theory = 2 philosophy = 2 #======================================================= f=eval(input()) a=python+math+english+physical+military_theory+philosophy print(f"你本学期选修了{a}个学分。") zf=f*(python+math+english+physical+military_theory+philosophy) print(f"你应缴纳的学费为{zf}元。") #======================================================= python123给的答案
python = 3 math = 4 english = 4 physical_education = 2 military_theory = 2 philosophy = 2 tuition_per_credit = int(input()) total_credits = (python + math + english + physical_education + military_theory + philosophy) total_tuition = total_credits * tuition_per_credit print(f'你本学期选修了{total_credits}个学分。') print(f'你应缴纳的学费为{total_tuition}元。')
类型:数值运算
描述
地球的半径是6371km,假设地球是一个规则的球体,完成以下计算并依次分行输出结果,结果保留2位小数,输出格式请参考输入输出示例。π值引用math库中常数pi的值。
计算地球表面积(表面积公式S = 4πR2) 计算地球体积(体积公式是V = 4πR3/3 注意:为避免浮点数除法顺序导致运算精度问题,必须严格按照本题所给公式顺序运算) 计算地球赤道的周长(圆周长公式是L = 2πR) 假设有一根绳子正好可以紧贴地球绕赤道一周,紧密的捆绑住地球。现在将绳子延长1米,仍围绕地球赤道一周,假设绳子与地球表面间空隙均匀,计算绳子与地球之间的空隙大小。 判断一只正常大小的老鼠能否从这个空隙穿过?可假设老鼠身体截面为圆柱,且圆柱最粗处直径为10cm,若空隙大小10cm,输出:“老鼠可以从空隙中钻过”,否则输出:“老鼠无法通过空隙”。根据判定结果进行输出时,可以用if 条件表达式进行判定,满足条件时的输出放在if分支下的缩进语句块中;不满足条件的输出放在与if对齐的else分支下的缩进语句块里。
示例
输出: 地球表面积为XXXX.XX平方米 地球体积为XXXX.XX立方米 地球赤道周长为XXXX.XX米 空隙大小为XXXX.XX米 老鼠可以从空隙中钻过/老鼠无法通过空隙 import math radius = 6371 * 1000 # 1. 计算地球表面积(表面积公式S = 4π(R**2)) #======================================================= # 补充你的代码 surface_area=4*math.pi*(radius**2) print(f'地球表面积为{surface_area}平方米') # 2. 计算地球体积(体积公式是V = 4π(R**3)/3) V=4*math.pi*(radius**3)/3 print(f'地球体积为{V:.2f}立方米') # 3. 计算地球赤道的周长(圆周长公式是L = 2πR) L=2*math.pi*radius print(f'地球赤道周长为{L:.2f}米') # 4.计算绳子与地球之间的空隙大小,结果保留2位小数 K=(2*math.pi*radius+1)/(2*math.pi)-radius print(f'空隙大小为{K:.2f}米') # 5.判断老鼠是否可以从空隙中钻过 if K>=0.1: print(f'老鼠可以从空隙中钻过') else: print('老鼠无法通过空隙') # 地球的半径是6371km,假设地球是一个规则的球体,完成以下计算并输出结果,结果保留2 位小数。 # π 值引用math 库中常数PI 的值。 # 1.
搭建环境为腾讯云 轻量级服务器
1.基础版Nginx 自定义安装目录 1.进入data目录 cd /data
2.创建文件夹 mkdir software
mkdir program
3.下载nginx压缩包 cd /data/software
wget http://nginx.org/download/nginx-1.22.0.tar.gz
4.解压nginx tar -xvf nginx-1.22.0.tar.gz
5.配置基本信息 ./configure --prefix=/data/program/nginx --with-http_ssl_module --with-http_stub_status_module
6.编译 make & make install
7.进入nginx启动目录 cd /data/program/nginx/sbin
8.启动命令 ./nginx
浏览器访问服务器ip
Nginx正常启动
2.修改Nginx配置文件 1.下载Nginx配置文件 cd /data/program/nginx/conf
下载nginx.conf
2.本地打开nginx.conf为记事本格式 注释掉
#location / {
#root html;
#index index.html index.htm;
#}
创建 这块是配置反向代理
location / {
proxy_pass http://ip:端口/目录/;
}
修改完后 保存文件
3.上传Nginx配置文件 上传该文件到/data/program/nginx/conf 路径
4.重启nginx 进入启动Nginx 启动目录
概述 Nginx是一个高性能的HTTP和反向代理服务器,特点是占有内存少,并发能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现特别出色。常见的软件代理服务还有HA proxy、Varnish和Squid等。
nginx的安装 安装nginx的依赖 yum install -y gcc gcc-c++ make libtool wget pcre pcre-devel zlib zlib-devel openssl openssl-devel 下载nginx wget http://nginx.org/download/nginx-1.23.1.tar.gz 解压压缩包 tar -zxvf nginx cd nginx-1.23.1/ 安装 ./configure make && make install 注意:安装完成后的路径为:/usr/local/nginx
启动 /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf 在本地浏览器访问80端口,看到如下画面,说明nginx启动成功。如果网络不通,请注意检查linux的防火墙是否开启。
常用命令 普通启动服务:/usr/local/nginx/sbin/nginx 配置文件启动:/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf 暴力停止服务:/usr/local/nginx/sbin/nginx -s stop 优雅停止服务:/usr/local/nginx/sbin/nginx -s quit 检查配置文件:/usr/local/nginx/sbin/nginx -t 重新加载配置:/usr/local/nginx/sbin/nginx -s reload 查看相关进程:ps -ef | grep nginx 测试反向代理 实现目标如下图所示,nginx监听80端口,并把请求转发到8080,在服务端启动一个tomcat监听8080用于测试。
nginx配置修改 修改nginx配置
vi /usr/local/nginx/conf/nginx.conf server { listen 80; server_name 192.
hadoop安装文档 1、准备安装文件 tar -zxvf hadoop-2.7.3.tar.gz 2、修改配置文件 cd /hadoop-2.7.3/etc/hadoop 创建所需文件
mkdir -p /usr/local/hadoop/tmp mkdir -p /usr/local/hadoop/data 2.1、修改core-site.xml 记得查看一下 9000端口是否被占用 netstat -ntlp
<!-- 指定HDFS中NameNode的地址 --> <property> <name>fs.defaultFS</name> <value>hdfs://golaxy2:9000</value> </property> <!-- 指定hadoop运行时产生文件的存储目录 --> <property> <name>hadoop.tmp.dir</name> <value>/usr/local/hadoop/tmp</value> </property> 2.2、修改hdfs-site.xml <!--数据冗余数--> <property> <name>dfs.replication</name> <value>3</value> </property> <!--secondary的地址--> <property> <name>dfs.namenode.secondary.http-address</name> <value>golaxy2:50090</value> </property> <!--关闭权限--> <property> <name>dfs.permissions</name> <value>false</value> </property> 2.3、修改 yarn-site.xml <!-- reducer获取数据的方式 --> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <!-- 指定YARN的ResourceManager的地址 --> <property> <name>yarn.resourcemanager.hostname</name> <value>主机名1</value> </property> <!-- 日志聚集功能使能 --> <property> <name>yarn.
K8s二进制部署CoreDNS遇到报错 DNS解析遇到If you don't see a command prompt, try pressing enter.1、出现的报错问题2、解决办法 DNS解析遇到If you don’t see a command prompt, try pressing enter. Error attaching, falling back to logs: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)
1、出现的报错问题 2、解决办法 为 system:anonymous 临时绑定一个 cluster-admin 的权限,即可解决报错。
[root@master01 k8s]#kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
介绍 本文介绍如何利用go-micro框架将应用注册到nacos,实际使用时可以利用go的可执行程序不需要专门依赖的特点,利用该程序的可执行文件将很多应用注册到nacos,例如vue等。
代码 package main import ( "fmt" "gitee.com/zjq528/microuser/config" "gitee.com/zjq528/microuser/handler" microuser "gitee.com/zjq528/microuser/proto/microuser" "github.com/micro/go-micro/v2" log "github.com/micro/go-micro/v2/logger" "github.com/micro/go-micro/v2/registry" "github.com/micro/go-plugins/registry/nacos/v2" "os" ) func NewRegistry(ip string) registry.Registry { //naocs地址,这里为了演示写成固定字符串,实际可以作为启动参数动态输入 ip = "127.0.0.1:8848" r := nacos.NewRegistry(func(options *registry.Options) { // nacos注册中心地址 options.Addrs = []string{ip} }) return r } func main() { // ip := os.Args[1] // fmt.Println("ip= "+ip) // 使用naocs配置中心 config.InitSetting() // 获取nacos注册中心实例 r := NewRegistry(ip) // New Service service := micro.NewService( micro.Name("test1"), micro.Address("127.0.0.1:9090"), micro.Version("latest"), micro.
I. 介绍 Stable Diffusion模型(稳定扩散模型)
是一种用于生成式建模的深度学习模型,它使用随机微分方程(SDE)来建模连续时间的动态过程。在图像、声音、文本等各种领域都有广泛的应用。与传统的生成式模型相比,Stable Diffusion模型能够生成更加高质量的样本。其原理是通过对随机微分方程进行离散化,将连续时间的过程转换为离散时间的过程,然后通过反向传播算法进行求解。
Google Colab 是一种基于云端的Jupyter笔记本环境,它提供了免费的GPU和TPU资源,使得深度学习训练变得更加便捷和高效。Colab可以直接在浏览器中运行,不需要单独安装任何软件,用户只需上传自己的代码和数据即可开始训练深度学习模型。Colab所提供的免费GPU和TPU资源,可以大幅缩短训练时间,并且不会消耗本地计算机的性能资源,大大降低了深度学习开发者的成本和门槛。
II. 准备工作 1:一个谷歌账号。注册地址
2:一个github账号。注册地址
3:一个Hugging Face账号。注册地址 4:准备好魔法梯子
III. 拉取Stable_Diffusion_WebUi_Altryne(云版带UI) 到这里,AI绘画门槛又又又降低了,从最开始需要花半天时间折腾的 Disco-Diffusion ,紧接着 Stable Diffusion 在 github 上开源,各家平台都推出了云平台,让用户通过轻松的点击、选择、输入就能生成一张张AI图。
再到现在!!!使用 webui 在 github 上开源了,不仅有手动教程、docker 教程,还有 Colab 傻瓜式的集成方案。
webui github 地址: https://github.com/sd-webui/sta
IV. 平台搭建 今天就来交大家如果来搭建和使用这个云平台。
第一步: 打开链接 初始化打开Google Colab官网地址 使用你的谷歌账号进行登录,登录后访问下面这个链接导入Jupyter Notebook
https://colab.research.google.com/github/altryne/sd-webui-colab/blob/main/Stable_Diffusion_WebUi_Altryne.ipynb
导入后效果为 如遇无法导入,请配置github账号并给予对应权限
第二步: 配置服务器 点击右上角的连接
点击确定,等待连接上
如下图所示出现对于的配置信息就算成功了
第三步: 设置 Token 总共分了三个步骤执行 点击这个 1 - Setup stage 左边的小箭头进行展开
勾选 download_if_missing ,然后到 https://huggingface.co/settings/tokens 复制你的 toekn 并填入
Java的三魂七魄 —— 高级多线程 目录 Java的三魂七魄 —— 高级多线程 一、多线程的创建二、线程安全问题三、线程通信问题四、更多实例 1.用线程同步的方法解决单例模式的线程安全问题2.银行存钱问题(线程安全问题)3.生产者消费者问题(线程通信问题) 一、多线程的创建 多线程的创建方法有:四种!!! #F44336
1.创建Thread子类 先上代码:
/** * 创建多线程的方法一: * 创建继承Thread的子类 * * @author 龙子贞 * @create 2020/3/7 18:41 */ //线程类 class NumCount extends Thread{ //run方法里是要执行的代码 @Override public void run() { //输出0-99 for (int i = 0; i < 100; i++) { System.out.println(NumCount.currentThread().getName()+":"+i); } } } //主类 public class MyThread { public static void main(String[] args) { //创建Thread子类的对象 NumCount nc1 = new NumCount(); //给线程起个名字 nc1.
时间范围:1942年至今。
时间精度:近年的数据大多为3小时数据,少量站点有1小时数据。
站点数量:近年为400多个。
气象要素:气温、气压、露点、风向风速、云量、降水量。
站点ID和站点名、经纬度的对应关系见isd-history.csv,该列表各列含义见isd-history.txt文件开头。isd-history.csv里包含了所有用到过的站点,包括大量现在已经不在使用的。经纬度是WGS-84坐标系。
参考博主链接: link的文章可知,通过频域点乘方式计算匹配滤波输出有三种方式,这里仅讨论前两种。第一种生成匹配滤波器的方式是对时域匹配滤波器进行fft变换,即将发射信号取共轭反转后进行fft;第二种方式是将发射信号变换到频域后取共轭。文中的弃置区我看得不是很明白,于是有了以下思考:
首先链接的文章也说了做fft补零是因为循环卷积和线性卷积的差异。
然后通过仿真发现方法二在没有距离延迟的情况下,频域匹配完通过ifft变换回时域并且fftshift后,峰值总是出现在 N f f t / 2 + 1 N_{fft}/2+1 Nfft/2+1 , 比如说64点的fft,峰值总是出现在33处。这是因为方法二在没有噪声的情况下,频域点乘后相位全为0,仅有幅度值。
而方法一的峰值似乎变得“捉摸不定”。于是通过公式进行比较。
假设发射信号 s t = [ s 0 , s 1 , … , s K − 1 ] T {s_t} = {[{s_0},{s_1}, \ldots ,{s_{K - 1}}]^T} st=[s0,s1,…,sK−1]T,根据方法一,匹配滤波器应为 [ s K − 1 ∗ , s K − 2 ∗ , … , s 0 ∗ ] T {[{s_{K-1}^*},{s_{K-2}^*}, \ldots ,{s_{0}^*}]^T} [sK−1∗,sK−2∗,…,s0∗]T,对其补零到 N N N点长度并做 N N N点fft有:
一.Class文件结构 1.概述 1.1 字节码文件的跨平台性 所有的JVM全部遵守Java虚拟机规范:Java SE Specifications,也就是说所有的JV环境都是一样的,这样一来字节码文件可以在各种JVM上运行。
1.2 Java的前端编译器
想要让一个Java程序正确地运行在JVM中,Java源码就必须要被编译为符合JVM规范的字节码。
前端编译器的主要任务就是负责将符合Java语法规范的Java代码转换为符合JVM规范的字节码文件。javac是一种能够将Java源码编译为字节码的前端编译器。
Javac编译器在将Java源码编译为一个有放的字节码文件过程中经历了4个步骤,分别是词法解析、语法解析、语义解析以及生成字节码。
前端编译器vs后端编译器
Java源代码的编译结果是字节码,那么肯定需要有一种编译器能够将Java源码编译为字节码,承担这个重要责任的就是配置在path环境变量中的javac编译器。javac是一种能够将Java源码编译为字节码的前端编译器。
HotSpot VM并没有强制要求前端编译器只能使用javac来编译字节码,其实只要编译结果符合JVM规范都可以被JVM所识别即可。在Java的前端编译器领域,除了javac之外,还有一种被大家经常用到的前端编译器,那就是内置在Eclipse中的ECJ(EclipseCompiler for Java)编译器。和Javac的全量式编译不同,EC是一种增量式编译器。
在Eclipse中,当开发人员编写完代码后,使用“Ctrl+S”快捷键时,ECJ编译器所采取的编译方案是把未编译部分的源码逐行进行编译,而非每次都全量编译。因此ECJ的编译效率会比javac更加迅速和高效,当然编译质量和javac相比大致还是一样的。ECJ不仅是Eclipse的默认内置前端编译器,在Tomcat中同样也是使用ECJ编译器来编译jsp文件。由于ECJ编译器是采用GPLv2的开源协议进行源代码公开,所以,大家可以登录eclipse官网下载ECJ编译器的源码进行二次开发。
默认情况下,IntelliJ IDEA 使用javac编译器。(还可以自己设置为AspectJ编译器ajc)
前端编译器并不会直接涉及编译优化等方面的技术,而是将这些具体优化细节移交给HotSpot的JIT编译器负责。
复习:AOT(静态提前编译器,Ahead Of Time Compiler)
1.3 透过字节码指令看代码细节 大厂面试题
类文件结构有几个部分?│
知道字节码吗?字节码都有哪些? Integer x = 5;int y = 5;比较x == y都经过哪些步骤?
public class IntegerTest { public static void main(String[] args) { Integer x = 5; int y = 5; System.out.println(x == y);//true Integer i1 = 10; Integer i2 = 10; System.
一、先了解SPU及SKU的相关概念: 我们在开发电商项目时,必须首先要了解两个概念,SPU与SKU是什么?这也是设计一个好的电商系统的必要前提。商系统实现了什么功能,大数情况下都是和商品模块相关联的。因此商品模块本身的实现要足够抽象、灵活、易于扩展,这样才能满足各种业务需求。而这一切的基础都建立在SPU和SKU的设计,所以说这两个概念,是设计好电商系统的关键。那SKU和SPU又分别是什么东西呢?
1、什么是SPU SPU (Standard Product Unit)即标准化产品单位,是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个SPU。
2、什么是SKU SKU(stock keeping unit)即库存量单位,是物理上不可分割的最小存货单元。正因为它在物理上是不可分割的最小存货单元,所以也就可以通过SKU来确定具体的货物存量。
如一件M码(四个尺码:S码、M码、L码、X码)的粉色(三种颜色:粉色、黄色、黑色)Zara女士风衣,其中M码、粉色就是一组SKU的组合。
SKU在生成时, 会根据属性生成相应的笛卡尔积,根据一组SKU可以确定商品的库存情况,那么上面的Zara女士风衣一共有4 * 3 = 12个SKU组合。
3、SPU和SKU的关联与区别 下面我们通过一个具体的电商流程来搞懂SPU和SKU。
常规的业务流程是这样的:用户通过一个标有商品简略信息的入口点进一个商品页面,这时会有几个不同的配置、颜色、尺寸供选择,用户选择时需要判断这个商品是否有库存。
这一系列操作中一个商品的页面会是一个SPU,最后检查的库存就是SKU。
但是为什么业务的流程是这样的呢?我们通过下图的来进行分析。,SKU和SPU是一种多对一的关系,SKU才是定义了产品下的具体商品。回到最开始的图我们来细说。
我们通过点击选择红框中的不同规格,可以组合出不同的华为笔记本电脑MateBook D 14商品(SKU),同时价格、库存量会有相应的变化。因为SPU+SKU才会得到一个具体的商品。
这就跟你去手机店跟柜员说我要买手机或者我要买华为笔记本电脑MateBook D 14,多少钱,人家柜员需要反问你啥电脑、什么型号、多大内存、啥颜色不然没法给你报价一个道理。
那SKU为什么称之为“库存量单位”?因为在采购商品的时候,不可能只写华为笔记本电脑MateBook D 14,相反采购单是根据颜色、容量、规格等SKU组合来区分采购的。入库也是根据不同的SKU组合来入库的,所以SKU称之为库存量单位。
就好比华为笔记本电脑MateBook D 14上市的时候,16GB+512GB的容量是缺货状态的,但其他容量是正常供应的。一个SPU拥有的规格越多,可以组合出来的SKU商品就越多,就拿华为笔记本电脑MateBook D 14中颜色和版本这两个规格来举例,每部华为笔记本电脑MateBook D 14最多可以有3*3=9种SKU组合,就代表华为笔记本电脑MateBook D 14这个产品下有9种商品,而每种SKU组合又可以分别定价。
总结
SPU和SKU都是属性的集合,SPU是公共属性的集合,SKU是独有属性的集合。SPU定义了产品,但不是商品,产品描述了商品的公共属性,不影响库存和价格。SKU定义了商品,是在SPU的基础上描述了其独有的属性,一个SPU可以拥有多个SKU,影响库存和价格。SKU是库存量的最小存货单位,也是用户能够选择的最小单位是实际购买的商品。每一个sku可以有独立的价格,当库存减少时减少的实际是sku的库。也可以这样认为只有确定了一个SPU才能获得关于这个SPU的所有SKU信息,而不能通过一组不同的SKU来确定SPU信息。 4、什么是商品的销售属性与基本属性,什么是基本属性的分组 4.1、基本属性分组(主要针对SPU来说)包括: 如以电脑为例,基本属性分组包括:
主体 、基本信息、机器规格、芯片、屏幕
如图:
4.2、基本属性(主要针对SPU来说)包括: 如以电脑为例,基本属性包括:
入网型号 上市年份 机身颜色 机身长度(mm) 机身材质工艺 CPU品牌 CPU型号
前言 一.jvm及java体系结构 1. Java及JVM简介 TIOBE语言热度排行榜
https://www.tiobe.com/tiobe-index/
世界上没有最好的编程语言,只有最适用于具体应用场景的编程语言。
java: 跨平台的语言
JVM: 跨语言的平台
随着Java7的正式发布,Java虚拟机的设计者们通过JSR-292规范基本实现在Java虚拟机平台上运行非Java语言编写的程序.Java虚拟机根本不关心运行在其内部的程序到底是使用何种编程语言编写的,它只关心"字节码"文件.也就是说java虚拟机拥有语言无关性,并不会单纯地与Java语言"终身绑定",只要其他编程语言的编译结果满足并包含Java虚拟机的内部指令集,符号表以及其他的辅助信息,它就是一个有效的字节码文件,就能够被虚拟机所识别并装载运行. 字节码 我们平时说的Java字节码,指的是用java语言编译成的字节码.准确的说任何能在jvm平台上执行的字节码格式都是一样的.所以应该统称为:jvm字节码.不同的编译器,可以编译出相同的字节码文件,字节码文件也可以在不同的jvm上运行.java虚拟机与java语言并没有必然的联系,它只与特定的二进制文件格式—Class文件格式所关联,Class文件中包含了java虚拟机指令集(或者称为字节码,Bytecodes)和符号表,还有一些其他辅助信息. 多语言混合编程 java平台上的多语言混合编程正成为主流,通过特定领域的语言取解决特定领域的问题是当前软件开发应对日趋复杂的项目需求的一个方向.试想一下,在一个项目之中,并行处理用Clojure语言编写,展示层使用过JRuby/Rails,中间层用过java,每个应用层都将使用不用的编程语言来完成,而且,接口对每一层的开发者都是透明的.各种语言之间的交互不存在任何困难,就像使用自己语言的原生API一样方便,因为它们最终都运行在一个虚拟机上.对这些运行与Java虚拟机上,Java之外的语言,来自系统级的,底层的支持正在迅速增强,以JSR-292为核心的一系列项目和功能改进(如DaVinci Machine项目,Nashorn引擎,InvokeDynamic指令,java.lang.invoke包等),推动Java虚拟机从"Java语言的虚拟机"想"多语言虚拟机"的方向发展. 2. Java发展的重大事件 Open JDK和Oracle JDK
在JDK11之前,OracleJDK中还会存在一些OpenJDK中没有的,闭源的功能.但在JDK11中,我们可以认为OpenJDK和OracleJDK代码实质上已经完全一致了.
3. 虚拟机与Java虚拟机 虚拟机 所谓虚拟机(Virtual Machine),就是一台虚拟的计算机,它是一款软件,用来执行一系列虚拟计算机指令.大体上,虚拟机可以分为系统虚拟机和程序虚拟机.大名鼎鼎的Visual Box,VMware就属于系统虚拟机,它们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台.程序虚拟机的典型代表就是Java虚拟机,它专门为执行单个计算机程序而设计,在java虚拟机中执行的指令我们称为Java字节码指令.无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制与虚拟机提供的资源中. Java虚拟机 java虚拟机是一台执行Java字节码的虚拟计算机,它拥有独立的运行机制,其运行的java字节码也未必由Java语言编译而成.JVM平台的各种语言可以共享Java虚拟机带来的跨平台型,优秀的垃圾回收器,以及科考的即时编译器.JAVA技术的核心就是Java虚拟机(JVM,Java Virtual Machine),因为所有的Java程序都运行在Java虚拟机内部. - 作用:
JAVA虚拟机就是二进制字节码的运行环境,负责装载字节码到其内部,解释/编译为对应平台上的机器指令执行.每一条Java指令,Java虚拟机规范都有详细定义,如怎么取操作数,怎么处理操作数,处理结果放在哪里. - 特点:
一次编译,到处运行. 2.自动内存管理. 3. 自动垃圾回收功能 JVM的位置
JVM是运行在操作系统之上的,它与硬件没有直接的交互.
4. JVM的整体结构 HotSpot VM是目前市面上高性能虚拟机的代表之一.它采用解释器与即时编译器并存的架构.在今天,Java程序的运行性能早已脱胎换骨,已经达到了可以和C/C++程序一较高下的地步. 谈谈你对JVM整体的理解?
类加载子系统运行时数据区(我们核心关注这里的栈,堆,方法区)执行引擎(解释器和JIT编译器共存) 5. Java代码执行流程 6. JVM的架构模型 Java编译器输入的指令流基本上是一种基于栈的指令集架构,另外一种指令集架构则是基于寄存器的指令集架构.
具体来说:这两种架构之间的区别:
基于栈式架构的特点: 涉及和实现更简单,适用于资源受限的系统.避开了寄存器的分配难题:适用零地址指令方式分配.指令流中的指令大部分是零地址指令,其执行过程依赖于操作栈.指令集更小,编译器容易实现.不需要硬件支持,可移植性更好,更好实现跨平台. 基于寄存器架构的特点: 典型的应用是x86的二进制指令集,比如传统的PC一级Android的Davlik虚拟机.指令集架构则完全依赖硬件,可移植性差.性能优秀和执行更高效.花费更少的指令取完成一项操作. 在大部分情况下,基于寄存器的指令集都以一地址指令,二地址指令和三地址指令,二基于栈式架构的指令集确实以零地址指令为主. 总结:
由于跨平台性的设计,Java的指令都是根据栈来设计的,不同平台CPU架构不同,所以不能涉及为基于寄存器的.优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令.时至今日,尽管嵌入式平台已经不是Java程序的主流运行平台了(准确来说应是HotSportVM的宿主环境已经不局限于嵌入式平台了),那么为什么不将架构更换为基于寄存器的架构呢? 7. JVM的生命周期 虚拟机的启动:
Java虚拟机的启动时通过引导类加载器(bootstrap class loader)创建一个初始类(initial class) 来完成的,这个类是由虚拟机的具体实现指定的.
Linux 网络环境配置方式
第一种方式:使用DHCP协议自动获取;
第二种方式:推荐使用这种,因为以后工作中需要让服务器具有固定IP,才能访问到,要是一直变换,就需要每次修改配置,十分麻烦
下面重点介绍如何将虚拟机IP设置为固定的
第一步: 设置虚拟机网络配置器的模式为NAT模式,操作方式如下图所示
第二步: VMware工具栏中选择编辑,然后点击虚拟网络编辑器
第三步: 进去之后,进入如下界面,1-3按如图所示的操作即可,选择VMnet8,选择NAT模式,然后选择将主机虚拟机适配器连接到此网络。在选择子网IP的时候,可以自己进行设置,但是一般遵守后面相应的子网掩码规则255.255.255.0,可以根绝自己需要修改。例如我按照上面图上方式填写
第四步: 点击NAT设置
第五步: 进入如下界面,查看网关IP是否与前面设置的子网在同一网段中,如果是可以直接退出,不是的话,需要将网关IP设置在和子网同一网段中。如下图我的配置是属于同一网段的,即可直接退出。
第六步: 查看可以给虚拟机配置的IP范围,第五步退出之后,点击DHCP配置,然后我们可以看到可以给虚拟机配置的IP的起始范围,后面我们给虚拟机指定的IP地址就需要在这个范围内
第七步: 修改配置文件来指定IP并可以连接到外网,在root用户终端下使用命令
vim /etc/sysconfig/network-scripts/ifcfg-ens33 要求:将ip地址配置的静态的即将原来的BOOTPROTO="dhcp"改为
BOOTPROTO="static"
同时指定IP地址、网关、域名解析器,例如我是下面这样配置的,注意看我这里设置的网关和第5步的网关是一模一样的,这样才能保证连通。同时可以看到给虚拟机指定的IP地址也是属于前面的子网网段,并且IP也在在第六步我们查看的IP其实范围内,只要在这个范围内就可以随意指定。
第八步: 通过以上步骤我们就成功给虚拟机设置了固定IP了,之后为了让我们的修改起作用,我们可以重启一下虚拟机。在重启虚拟机后,可以在Linux终端查看一下自己IP配置信息,Linux下查看自己的IP信息:ifconfig,在终端输入ifconfig即可看到虚拟机IP地址已经改为我们自己指定的IP了。
导读 由于Golang是编译型语言(非脚本型语言),如果你想在Golang程序中获取当前执行目录将是一件非常蛋疼的事情。 以前大家最折中的解决方案就是通过启动传参或是环境变量将路径手动传递到程序,而今天我在看日志库的时候发现了一种新的解决方案。
Go程序两种不同的执行方式 用Go编写的程序有两种执行方式,go run和go build
通常的做法是go run用于本地开发,用一个命令中快速测试代码确实非常方便;在部署生产环境时,我们会通过go build构建出二进制文件然后上传到服务器再去执行。 两种启动方式会产生什么问题? 那么两种启动方式下,获取到当前执行路径会产生什么问题?
话不多说,我们直接上代码
我们编写获取当前可执行文件路径的方法
package main import ( "fmt" "log" "os" "path/filepath" ) func main() { fmt.Println("getCurrentAbPathByExecutable = ", getCurrentAbPathByExecutable()) } // 获取当前执行程序所在的绝对路径 func getCurrentAbPathByExecutable() string { exePath, err := os.Executable() if err != nil { log.Fatal(err) } res, _ := filepath.EvalSymlinks(filepath.Dir(exePath)) return res } 首先通过go run启动
D:\Projects\demo>go run main.go getCurrentAbPathByExecutable = C:\Users\XXX\AppData\Local\Temp\go-build216571510\b001\exe 再尝试go build执行
D:\Projects\demo>go build & demo.exe getCurrentAbPathByExecutable = D:\Projects\demo 通过对比执行结果,我们发现两种执行方式,我们获取到了不同的路径。而且很明显,go run获取到的路径是错误的。