首页 文章 精选 留言 我的

精选列表

搜索[云数据库 Redis®],共10034篇文章
优秀的个人博客,低调大师

Docker 上传镜像&拉取镜像

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36367789/article/details/81623850 与git相似,docker也有自己的镜像仓库,官方仓库网站是https://hub.docker.com/,其实我们平时docker pull xxx就是从该仓库得到的镜像(在不设置国内镜像加速的情况下)。它和git仓库很相似。 创建账号 DockerHub:https://hub.docker.com/ 很多人在这里就出了问题,为什么都填完了但是不能点注册按钮呢?因为该网站目前来说注册是需要翻墙的,注册成功后再关闭翻墙。 我重新上传一个项目做示范,该镜像是从hub上pull到的一个nginx镜像,我把它上传到我的公开仓库。 上传镜像 先登录docker hub账号。 docker login [root@FantJ ~]# docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username (fantj): fantj Password: Login Succeeded [root@FantJ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/openjdk 8-jre bef23b4b9cac 2 weeks ago 443 MB docker.io/nginx latest ae513a47849c 4 weeks ago 109 MB [root@FantJ ~]# docker tag docker.io/nginx fantj/nginx [root@FantJ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/openjdk 8-jre bef23b4b9cac 2 weeks ago 443 MB fantj/nginx latest ae513a47849c 4 weeks ago 109 MB docker.io/nginx latest ae513a47849c 4 weeks ago 109 MB [root@FantJ ~]# docker push fantj/nginx The push refers to a repository [docker.io/fantj/nginx] 7ab428981537: Mounted from library/nginx 82b81d779f83: Mounted from library/nginx d626a8ad97a1: Mounted from library/nginx latest: digest: sha256:e4f0474a75c510f40b37b6b7dc2516241ffa8bde5a442bde3d372c9519c84d90 size: 948 [root@FantJ ~]# 流程大概是:登录->tag操作->push 注:tag 的第二个参数的前缀是你的hub账户名 拉取镜像 我先把服务器上的镜像删除掉,然后再从hub中拉取镜像。 # 删除本地fantj/nginx镜像 [root@FantJ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/openjdk 8-jre bef23b4b9cac 2 weeks ago 443 MB fantj/nginx latest ae513a47849c 4 weeks ago 109 MB docker.io/nginx latest ae513a47849c 4 weeks ago 109 MB [root@FantJ ~]# docker rmi fantj/nginx Untagged: fantj/nginx:latest Untagged: fantj/nginx@sha256:e4f0474a75c510f40b37b6b7dc2516241ffa8bde5a442bde3d372c9519c84d90 [root@FantJ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/openjdk 8-jre bef23b4b9cac 2 weeks ago 443 MB docker.io/nginx latest ae513a47849c 4 weeks ago 109 MB # 从hub中拉取fantj/nginx镜像 [root@FantJ ~]# docker pull fantj/nginx Using default tag: latest Trying to pull repository docker.io/fantj/nginx ... latest: Pulling from docker.io/fantj/nginx Digest: sha256:e4f0474a75c510f40b37b6b7dc2516241ffa8bde5a442bde3d372c9519c84d90 Status: Downloaded newer image for docker.io/fantj/nginx:latest [root@FantJ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/openjdk 8-jre bef23b4b9cac 2 weeks ago 443 MB docker.io/fantj/nginx latest ae513a47849c 4 weeks ago 109 MB docker.io/nginx latest ae513a47849c 4 weeks ago 109 MB [root@FantJ ~]#

优秀的个人博客,低调大师

Class文件结构&字节码指令

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36367789/article/details/81605625 class文件结构 无符号数 表 Class文件设计理念和意义 1. 魔数magic 证明magic作用 minor_version、major_version 2. constant_pool_count 3. constant_pool[]常量池 3.1 CONSTANT_Class_info结构 3.2 CONSTANT_Fieldref_info, CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info结构 3.3 CONSTANT_String_info结构 3.4CONSTANT_Integer_info和CONSTANT_Float_info结构 3.5CONSTANT_Long_info和CONSTANT_Double_info结构 3.6 CONSTANT_NameAndType_info结构 3.7 CONSTANT_Utf8_info结构 3.8 CONSTANT_MethodHandle_info结构 3.9 CONSTANT_MethodType_info结构 3.10 CONSTANT_InvokeDynamic_info结构 4. access_flags:访问标志 5. this_class:类索引 6. super_class:父类索引 7. interfaces_count:接口计数器 8. interfaces[]:接口表 9. fields_count:字段计数器 10. fields[]:字段表 11. methods_count:方法计数器 12. methods[]:方法表 13. attributes_count:属性计数器 14. attributes[]:属性表 14.1 ConstantValue属性 14.2 Code属性 14.3 StackMapTable属性 字节码指令 常量入栈指令 局部变量值转载到栈中指令 将栈顶值保存到局部变量中指令 wide指令 通用(无类型)栈操作指令 类型转换指令 整数运算 浮点运算 逻辑运算——移位运算 逻辑运算——按位布尔运算 控制流指令——条件跳转指令 控制流指令——比较指令 控制流指令——无条件跳转指令 控制流指令——表跳转指令 控制流指令——异常和finally 对象操作指令 数组操作指令 方法调用指令 方法返回指令 线程同步指令 一个简单的demo分析 Test.java javap -v Test.class class文件结构 Class文件存储的内容称为字节码(ByteCode),包含了JVM指令集和符号表以及若干其他辅助信息。 class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在Class文件中,中间没有添加任何分隔符,整个Class文件中存储的内容几乎全部是程序运行的必要的数据,没有空隙存在。 当遇到8位字节以上的空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。 Class文件中有两种数据类型,分别是无符号数和表。 无符号数 无符号数属于基本的数据类型,以u1、u2、u4、u8来表示一个字节、两个字节…的无符号数;无符号数用来描述数字、索引引用、数量值或UTF-8编码构成的字符串值。 表 表是由多个无符号数或其他表作为数据项构成的复合数据类型,一般以”_info”结尾,用来描述class文件的数据结构。 特点:节省存储空间,提高处理性能 ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; } 魔数 Class文件版本 常量池 访问标志 类索引,父类索引,接口索引集合 字段表集合 方法表集合 属性表集合 u2表示无符号数2个字节 u4表示无符号数4个字节 Class文件设计理念和意义 1. 魔数magic 魔数的唯一作用是确定这个文件是否为一个能被虚拟机所接受的Class文件。魔数值固定为0xCAFEBABE,不会改变。 证明magic作用 创建一个class文件 magic.class ,内容是magic test,直接运行java magic操作: 84407@FantJ MINGW64 ~/Desktop $ java magictest ▒▒▒▒: ▒▒▒▒▒▒▒▒ magictest ʱ▒▒▒▒ LinkageError java.lang.ClassFormatError: Incompatible magic value 1886741100 in class file magictest 报错意思是:magic矛盾,然后给了个magic value的十进制数,那么可以识别的magic十进制应该是多少呢。 应该是3405691582 那么,然后我用javac编译的正常java文件生成class文件,用binary viewer 查看: minor_version、major_version 魔数往后后面四位:表示字节码版本,分别表示Class文件的副、主版本。当今用的最广的几个版本: jdk1.8:52 jdk1.7:51 jdk1.6:50 对应版本号是52,是jdk1.8 版本向下兼容 2. constant_pool_count 常量池计数器,值等于constant_pool表中的成员数加1,占用两个字节 3. constant_pool[]常量池 Java虚拟机指令执行时依赖常量池(constant_pool)表中的符号信息。 所有的常量池项都具有如下通用格式: cp_info { u1 tag; u1 info[]; } info[]项的内容tag由的类型所决定。tag有效的类型和对应的取值在下表列出 常量类型 值 CONSTANT_Class 7 CONSTANT_Fieldref 9 CONSTANT_Methodref 10 CONSTANT_InterfaceMethodref 11 CONSTANT_String 8 CONSTANT_Integer 3 CONSTANT_Float 4 CONSTANT_Long 5 CONSTANT_Double 6 CONSTANT_NameAndType 12 CONSTANT_Utf8 1 CONSTANT_MethodHandle 15 CONSTANT_MethodType 16 CONSTANT_InvokeDynamic 18 3.1 CONSTANT_Class_info结构 表示类或接口 CONSTANT_Class_info { u1 tag; u2 name_index; } name_index必须是对常量池的一个有效索引 3.2 CONSTANT_Fieldref_info, CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info结构 字段: CONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; } 方法: CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } 接口方法: CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } class_index必须是对常量池的有效索引,常量池在该索引处的项必须是CONSTANT_Class_info结构,表示一个类或接口,当前字段或方法是这个类或接口的成员。 CONSTANT_Methodref_info结构的class_index项的类型必须是类(不能是接口)。CONSTANT_InterfaceMethodref_info结构的class_index项的类型必须是接口(不能是类)。CONSTANT_Fieldref_info结构的class_index项的类型既可以是类也可以是接口。 name_and_type_index必须是对常量池的有效索引,表示当前字段或方法的名字和描述符。 在一个CONSTANT_Fieldref_info结构中,给定的描述符必须是字段描述符。而CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info中给定的描述符必须是方法描述符。 3.3 CONSTANT_String_info结构 用来表示String的结构 CONSTANT_String_info { u1 tag; u2 string_index; } string_index必须是对常量池的有效索引,常量池在该索引处的项必须是CONSTANT_Utf8_info 结构,表示一组Unicode码点序列,这组Unicode码点序列最终会被初始化为一个String对象。 3.4CONSTANT_Integer_info和CONSTANT_Float_info结构 表示4字节(int和float)的数值常量: CONSTANT_Integer_info { u1 tag; u4 bytes; } CONSTANT_Float_info { u1 tag; u4 bytes; } 3.5CONSTANT_Long_info和CONSTANT_Double_info结构 表示8字节(long和double)的数值常量 CONSTANT_Long_info { u1 tag; u4 high_bytes; u4 low_bytes; } CONSTANT_Double_info { u1 tag; u4 high_bytes; u4 low_bytes; } 3.6 CONSTANT_NameAndType_info结构 表示字段或方法,但是和前面介绍的3个结构不同,CONSTANT_NameAndType_info结构没有标识出它所属的类或接口 CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index; } name_index项的值必须是对常量池的有效索引,常量池在该索引处的项必须是CONSTANT_Utf8_info结构,这个结构要么表示特殊的方法名,要么表示一个有效的字段或方法的非限定名(Unqualified Name)。 descriptor_index项的值必须是对常量池的有效索引,常量池在该索引处的项必须是CONSTANT_Utf8_info结构,这个结构表示一个有效的字段描述符或方法描述符。 3.7 CONSTANT_Utf8_info结构 用于表示字符串常量的值 CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; } CONSTANT_Utf8_info结构中的内容是以length属性确定长度的 3.8 CONSTANT_MethodHandle_info结构 表示方法句柄 CONSTANT_MethodHandle_info { u1 tag; u1 reference_kind; u2 reference_index; } reference_kind项的值必须在1至9之间(包括1和9),它决定了方法句柄的类型。 1. 如果reference_kind项的值为1(REF_getField)、2(REF_getStatic)、3(REF_putField)或4(REF_putStatic),那么常量池在reference_index索引处的项必须是CONSTANT_Fieldref_info结构,表示由一个字段创建的方法句柄。 2. 如果reference_kind项的值是5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或8(REF_newInvokeSpecial),那么常量池在reference_index索引处的项必须是CONSTANT_Methodref_info结构,表示由类的方法或构造函数创建的方法句柄。 3. 如果reference_kind项的值是9(REF_invokeInterface),那么常量池在reference_index索引处的项必须是CONSTANT_InterfaceMethodref_info结构,表示由接口方法创建的方法句柄。 4. 如果reference_kind项的值是5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或9(REF_invokeInterface),那么方法句柄对应的方法不能为实例初始化()方法或类初始化方法()。 5. 如果reference_kind项的值是8(REF_newInvokeSpecial),那么方法句柄对应的方法必须为实例初始化()方法。 3.9 CONSTANT_MethodType_info结构 表示方法类型 CONSTANT_MethodType_info { u1 tag; u2 descriptor_index; } 3.10 CONSTANT_InvokeDynamic_info结构 表示invokedynamic指令所使用到的引导方法(Bootstrap Method)、引导方法使用到动态调用名称(Dynamic Invocation Name)、参数和请求返回类型、以及可以选择性的附加被称为静态参数(Static Arguments)的常量序列。 CONSTANT_InvokeDynamic_info { u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index; } bootstrap_method_attr_index项的值必须是对当前Class文件中引导方法表的bootstrap_methods[]数组的有效索引。 name_and_type_index项的值必须是对当前常量池的有效索引,常量池在该索引处的项必须是CONSTANT_NameAndType_info结构,表示方法名和方法描述符。 4. access_flags:访问标志 访问标志,access_flags是一种掩码标志,用于表示某个类或者接口的访问权限及基础属性。access_flags的取值范围和相应含义见下表。 标记名 值 含义 ACC_PUBLIC 0x0001 可以被包的类外访问。 ACC_FINAL 0x0010 不允许有子类。 ACC_SUPER 0x0020 当用到invokespecial指令时,需要特殊处理的父类方法。 ACC_INTERFACE 0x0200 标识定义的是接口而不是类。 ACC_ABSTRACT 0x0400 不能被实例化。 ACC_SYNTHETIC 0x1000 标识并非Java源码生成的代码。 ACC_ANNOTATION 0x2000 标识注解类型 ACC_ENUM 0x4000 标识枚举类型 5. this_class:类索引 this_class的值必须是对constant_pool表中项目的一个有效索引值。 是一个对constant_pool表中项目的一个有效索引值,表示指向常量池的第几个位置。 6. super_class:父类索引 表示这个Class文件所定义的类的直接父类,如果Class文件的super_class的值为0,那这个Class文件只可能是定义的是java.lang.Object类,只有它是唯一没有父类的类 是一个对constant_pool表中项目的一个有效索引值,表示指向常量池的第几个位置。 7. interfaces_count:接口计数器 表示有这个类有几个接口。 8. interfaces[]:接口表 成员所表示的接口顺序和对应的源代码中给定的接口顺序(从左至右)一样,即interfaces[0]对应的是源代码中最左边的接口。 是一个对constant_pool表中项目的一个有效索引值,表示指向常量池的第几个位置。 表示当前类或接口的直接父接口数量 9. fields_count:字段计数器 表示当前Class文件fields[]数组的成员个数 10. fields[]:字段表 每个成员都必须是一个fields_info结构的数据项,描述当前类或接口声明的所有字段,但不包括从父类或父接口继承的部分。 用于表示当前类或接口中某个字段的完整描述 field_info { u2 access_flags; u2 name_index; //对常量池的一个有效索引 u2 descriptor_index; //对常量池的一个有效索引 u2 attributes_count; //当前字段的附加属性的数量 attribute_info attributes[attributes_count]; } access_flags项的值是用于定义字段被访问权限和基础属性的掩码标志。access_flags的取值范围和相应含义见下表所示: 标记名 值 说明 ACC_PUBLIC 0x0001 public,表示字段可以从任何包访问。 ACC_PRIVATE 0x0002 private,表示字段仅能该类自身调用。 ACC_PROTECTED 0x0004 protected,表示字段可以被子类调用。 ACC_STATIC 0x0008 static,表示静态字段。 ACC_FINAL 0x0010 final,表示字段定义后值无法修改。 ACC_VOLATILE 0x0040 volatile,表示字段是易变的。 ACC_TRANSIENT 0x0080 transient,表示字段不会被序列化。 ACC_SYNTHETIC 0x1000 表示字段由编译器自动产生。 ACC_ENUM 0x4000 enum,表示字段为枚举类型。 attributes表的每一个成员的值必须是attribute结构,一个字段可以有任意个关联属性。 11. methods_count:方法计数器 methods_count的值表示当前Class文件methods[]数组的成员个数,Methods[]数组中每一项都是一个method_info结构的数据项。 12. methods[]:方法表 method_info结构可以表示类和接口中定义的所有方法,包括实例方法、类方法、实例初始化方法方法和类或接口初始化方法方法。methods[]数组只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法。 methods[]数组中的每个成员都必须是一个method_info结构的数据项,用于表示当前类或接口中某个方法的完整描述。 method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; } access_flags项的值是用于定义当前方法的访问权限和基本属性的掩码标志,access_flags的取值范围和相应含义见下表所示。 标记名 值 说明 ACC_PUBLIC 0x0001 public,方法可以从包外访问 ACC_PRIVATE 0x0002 private,方法只能本类中访问 ACC_PROTECTED 0x0004 protected,方法在自身和子类可以访问 ACC_STATIC 0x0008 static,静态方法 ACC_FINAL 0x0010 final,方法不能被重写(覆盖) ACC_SYNCHRONIZED 0x0020 synchronized,方法由管程同步 ACC_BRIDGE 0x0040 bridge,方法由编译器产生 ACC_VARARGS 0x0080 表示方法带有变长参数 ACC_NATIVE 0x0100 native,方法引用非java语言的本地方法 ACC_ABSTRACT 0x0400 abstract,方法没有具体实现 ACC_STRICT 0x0800 strictfp,方法使用FP-strict浮点格式 ACC_SYNTHETIC 0x1000 方法在源文件中不出现,由编译器产生 name_index和 descriptor_index 两属性是对常量池的一个有效索引 attributes_count的项的值表示这个方法的附加属性的数量。 attributes 表的每一个成员的值必须是attribute结构,一个方法可以有任意个与之相关的属性。 13. attributes_count:属性计数器 attributes表中每一项都是一个attribute_info结构的数据项。 attributes_count的值表示当前Class文件attributes表的成员个数。 14. attributes[]:属性表 attributes表的每个项的值必须是attribute_info结构,在Class文件格式中的ClassFile结构、field_info结构,method_info结构和Code_attribute结构都有使用,所有属性的通用格式如下: attribute_info { u2 attribute_name_index; u4 attribute_length; u1 info[attribute_length]; } attribute_name_index必须是对当前Class文件的常量池的有效16位无符号索引。表示当前属性的名字。 attribute_length项的值给出了跟随其后的字节的长度,这个长度不包括attribute_name_index和attribute_name_index项的6个字节。 14.1 ConstantValue属性 ConstantValue属性是定长属性,位于field_info结构的属性表中。如果该字段为静态类型(即field_info结构的access_flags项设置了ACC_STATIC标志),则说明这个field_info结构表示的常量字段值将被分配为它的ConstantValue属性表示的值,这个过程也是类或接口申明的常量字段(Constant Field)初始化的一部分。这个过程发生在引用类或接口的类初始化方法执行之前。 ConstantValue_attribute { u2 attribute_name_index; u4 attribute_length; u2 constantvalue_index; } attribute_name_index项的值,必须是一个对常量池的有效索引。 attribute_length项的值固定为2。 constantvalue_index项的值,必须是一个对常量池的有效索引。 14.2 Code属性 Code属性是一个变长属性,位于method_info结构的属性表。一个Code属性只为唯一一个方法、实例类初始化方法或类初始化方法保存Java虚拟机指令及相关辅助信息。所有Java虚拟机实现都必须能够识别Code属性。如果方法被声明为native或者abstract类型,那么对应的method_info结构不能有明确的Code属性,其它情况下,method_info有必须有明确的Code属性。 Code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count]; } attribute_name_index项的值必须是对常量池的有效索引 attribute_length项的值表示当前属性的长度,不包括开始的6个字节。 max_stack项的值给出了当前方法的操作数栈在运行执行的任何时间点的最大深度。 max_locals项的值给出了分配在当前方法引用的局部变量表中的局部变量个数,包括调用此方法时用于传递参数的局部变量。long和double型的局部变量的最大索引是max_locals-2,其它类型的局部变量的最大索引是max_locals-1. code_length项给出了当前方法的code[]数组的字节数,code_length的值必须大于0,即code[]数组不能为空。 code[]数组给出了实现当前方法的Java虚拟机字节码。 exception_table_length项的值给出了exception_table[]数组的成员个数量。 exception_table[]数组的每个成员表示code[]数组中的一个异常处理器(Exception Handler)。exception_table[]数组中,异常处理器顺序是有意义的(不能随意更改)。 start_pc和end_pc两项的值表明了异常处理器在code[]数组中的有效范围。 handler_pc项表示一个异常处理器的起点 如果catch_type项的值不为0,那么它必须是对常量池的一个有效索引 attributes_count项的值给出了Code属性中attributes表的成员个数。 属性表的每个成员的值必须是attribute结构。一个Code属性可以有任意数量的可选属性与之关联。 14.3 StackMapTable属性 StackMapTable属性是一个变长属性,位于Code属性的属性表中。这个属性会在虚拟机类加载的类型阶段被使用。 StackMapTable_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_entries; stack_map_frame entries[number_of_entries]; } attribute_name_index项的值必须是对常量池的有效索引 attribute_length项的值表示当前属性的长度,不包括开始的6个字节。 number_of_entries项的值给出了entries表中的成员数量。Entries表的每个成员是都是一个stack_map_frame结构的项。 entries表给出了当前方法所需的stack_map_frame结构。 …更多的属性就不在这一一贴了,太多了,需要的时候查官方文档即可:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4 字节码指令 java虚拟机指令由一个字节长度的,代表某种特定操作含义的数字(称之为操作码),以及随后的代表此操作所需参数的操作数而构成。 操作码的长度为1个字节,所以最大只有256条 常量入栈指令 局部变量值转载到栈中指令 将栈顶值保存到局部变量中指令 wide指令 通用(无类型)栈操作指令 类型转换指令 整数运算 浮点运算 逻辑运算——移位运算 逻辑运算——按位布尔运算 控制流指令——条件跳转指令 控制流指令——比较指令 控制流指令——无条件跳转指令 控制流指令——表跳转指令 控制流指令——异常和finally 对象操作指令 数组操作指令 方法调用指令 方法返回指令 线程同步指令 指令参考:https://blog.csdn.net/web_code/article/details/12164733 一个简单的demo分析 Test.java public class Test { public static void main(String[] args) { int a = 10; int b = 20; int c = a+b; System.out.println(c); } } javap -v Test.class #2 = Fieldref #24.#25 // java/lang/System.out:Ljava/io/PrintStream; #3 = Methodref #26.#27 // java/io/PrintStream.println:(I)V public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: bipush 10 //把10扩展成int入栈 2: istore_1 //将栈顶int类型值保存到局部变量1中 3: bipush 20 //把20扩展成int入栈 5: istore_2 //将栈顶int类型值保存到局部变量2中 6: iload_1 //从局部变量1中装载int类型值入栈 7: iload_2 //从局部变量2中装载int类型值入栈 8: iadd // 将栈顶两int类型数相加,结果入栈。 9: istore_3 //将栈顶int类型值保存到局部变量3中 10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;获取静态字段的值。#2表示常量池的索引 13: iload_3 14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 运行时方法绑定调用方法。 17: return //void函数返回。

优秀的个人博客,低调大师

Java Web && PHP 对比——嵌入篇

Java Web学习笔记——同时与PHP对比 博主在在学习Java Web,因为之前有学习过PHP,感觉二者有相似之处也有不同之处。所以在学习Java Web过程中,总结一下,希望能有所收获。 1、JSP的java代码嵌入和PHP文件中的PHP代码嵌入。(二者必须是Jsp文件或PHP文件才能实现嵌入html元素) 1.1JSP: //for循环输出表单 <% for ($i=0; $i < 5 ; $i++) { //for循环 %> <tr> <td>张三</td> <td>29</td> </tr> <% } //for循环结束 %> 1.2PHP: //for循环输出表单 <?php for ($i=0; $i < 5 ; $i++) { //for循环 ?> <tr> <td>张三</td> <td>29</td> </tr> <?php } //for循环结束 ?> 输出

优秀的个人博客,低调大师

Java Web &amp;&amp; PHP 对比——Cookie篇

Java Web学习笔记——同时与PHP对比 博主在在学习Java Web,因为之前有学习过PHP,感觉二者有相似之处也有不同之处。所以在学习Java Web过程中,总结一下,希望能有所收获。 2、JSP和PHP的Cookie设置和获取 2.1JSP: <% //设置cookie Cookie name = new Cookie("name","JSP"); // 设置cookie过期时间为1小时。 name.setMaxAge(60*60); // 在响应头部添加cookie response.addCookie( name ); //获取Cookie Cookie[] cookies =request.getCookies(); if( cookies != null ){ for (int i = 0; i < cookies.length; i++){ cookie = cookies[i]; out.print(cookie.getName());+":"+cookie.getValue()+"</br>"); } %> 2.2PHP: <?php setcookie("user", "PHP", time()+3600); //设置cookie echo $_COOKIE["user"]; // 输出 cookie 值 ?>

优秀的个人博客,低调大师

Android LruCache &amp;amp; DiskLruCache cooperate working in ListView

package zhangphil.cache; import android.app.ListActivity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.os.Bundle; import android.util.Log; import android.util.LruCache; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.security.MessageDigest; public class MainActivity extends ListActivity { private LruCache<String, Bitmap> mLruCache; private DiskLruCache mDiskLruCache; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); int CACHE_SIZE = 8 * 1024 * 1024; mLruCache = new LruCache(CACHE_SIZE); try { mDiskLruCache = DiskLruCache.open(this.getCacheDir(), 1, 1, CACHE_SIZE * 10); } catch (Exception e) { e.printStackTrace(); } ArrayAdapter mAdapter = new ArrayAdapter(this, 0) { @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { ImageView image = new ImageView(getContext()); load(R.mipmap.ic_launcher, image); return image; } @Override public int getCount() { return 20; } }; setListAdapter(mAdapter); } private void load(int id, ImageView image) { String key = null; if (id == R.mipmap.ic_launcher) { key = getMD5("R.mipmap.ic_launcher"); } //首先查找LruCache中的缓存 Bitmap bmp = mLruCache.get(key); if (bmp == null) { Log.d("LruCache缓存", "没有,继续深入到DiskLruCache读取。"); bmp = readFromDiskLruCache(key); if (bmp == null) { Log.d("LruCache与DiskLruCache", "没有缓存,开始创建新数据资源并缓存之。"); bmp = BitmapFactory.decodeResource(getResources(), id); //初次创建新资源,更新到DiskLruCache writeToDiskLruCache(key, bmp); } else { image.setImageBitmap(bmp); } //更新到LruCache缓存中,以待下一次使用。 mLruCache.put(key, bmp); Log.d("LruCache缓存", "写入完成。"); } else { //命中缓存 Log.d("LruCache缓存", "已有,复用。"); image.setImageBitmap(bmp); } } private void writeToDiskLruCache(String key, Bitmap bmp) { try { DiskLruCache.Editor editor = mDiskLruCache.edit(key); //把Bitmap转化为byte数组存储 ByteArrayOutputStream baos = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] bytes = baos.toByteArray(); //再次把Bitmap数组写进为DiskLruCache准备的输出流。 OutputStream os = editor.newOutputStream(0); os.write(bytes); os.flush(); //正式写入DiskLruCache editor.commit(); Log.d("DiskLruCache缓存", "写入缓存资源完毕。"); } catch (Exception e) { e.printStackTrace(); } } private Bitmap readFromDiskLruCache(String key) { DiskLruCache.Snapshot snapShot = null; try { snapShot = mDiskLruCache.get(key); } catch (Exception e) { e.printStackTrace(); } Bitmap bmp = null; if (snapShot != null) { Log.d("DiskLruCache缓存", "发现资源,复用。"); InputStream is = snapShot.getInputStream(0); bmp = BitmapFactory.decodeStream(is); } else { Log.d("DiskLruCache缓存", "没有发现缓存资源。"); } return bmp; } private String getMD5(String msg) { MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); } catch (Exception e) { e.printStackTrace(); } md.reset(); md.update(msg.getBytes()); byte[] bytes = md.digest(); String result = ""; for (byte b : bytes) { result += String.format("%02x", b); } return result; } }

优秀的个人博客,低调大师

Android -- ADT变化&amp;aar&amp;Lint

Switch Case switch case 常用的使用方法: switch(v.getId()){ case R.id.btn1: doClick1(); break; } 在ADT中的改变 在正常的 Android 项目中,资源R类里的常量是这样声明的: public static final int main=0x7f030004; 然而,到 ADT 14为止,在类库项目中,他们会被这样声明: public static int main=0x7f030004; 原因 在库项目中这些常量都不是final的。原因很简单:当多个库项目整合时,字段的实际值(必须是唯一的)可能会出现碰撞。在ADT 14 之前,所有这样的字段都是final的,所以导致所有的库被使用的时候,主项目必须编译他们的所有资源和相关 Java 代码。这样的性能是很差的,因为它使构建的速度非常慢。它还阻碍了不包含源代码的库项目的分发,限制库项目的使用范围。 字段不再是 final 的原因是意味着库jar包可以只编译一次,并且能直接在其他项目中复用。以及允许分发库项目的二进制版本(将在 r15出现),这使得构建更快。 影响 以下代码不能再编译通过: switch(v.getId()){ case R.id.btn1: doClick1(); break; } 只能换成: if(v.getId() == R.id.btn1){ doClick1(); } //else if(...){....}else{...} 我是天王盖地虎的分割线 aar “aar”包是 Android 的类库项目的二进制发行包。 文件扩展名是.aar,maven 项目类型应该也是aar,但文件本身是带有以下各项的 zip 文件: /AndroidManifest.xml(mandatory) /classes.jar(mandatory) /res/(mandatory) /R.txt(mandatory) /assets/(optional) /libs/.jar(optional) /jni//.so(optional) /proguard.txt(optional) /lint.jar(optional) 这些条目是直接位 zip 文件根目录的。 R.txt 文件是aapt带参数--output-text-symbols的输出结果。 我是天王盖地虎的分割线 Lint Android lint工具是一个静态代码分析工具,检查你的Android项目源文件潜在的bug,并优化改进,确保正确性、安全性、性能、可用性、可访问性和国际化。 概述 Android SDK提供了一个代码扫描工具,称为lint。可以帮助您轻松地识别并纠正问题与结构质量的代码,不必执行应用程序或编写任何测试用例。每个问题检测到该工具报告的一个描述消息和严重性级别,您可以快速地优先考虑的关键改进。您还可以配置一个问题的严重性级别,忽略不相关的问题,或提高的严重程度。这个工具有一个命令行接口,所以您可以很容易地集成到您的自动化测试过程。 Lint工具可以检查你android工程潜在的bug和优化改进,以确保正确性、安全性、性能、可用性、可访问性和国际性。您可以从命令行运行lint,或eclipse中运行lint。 lint优点 除了测试Android应用程序满足其功能需求,重要的是要确保代码没有结构性问题。代码结构简陋的可靠性和效率的影响你的Android应用程序,使您的代码很难维护。例如,如果XML资源文件包含未使用的名称空间,这占用空间并产生不必要的处理。其他的结构性问题,比如使用弃用元素或API调用所不支持的目标API版本,可能会导致代码未能正确地运行。 Android lint是在ADT 16提供的新工具,它是一个代码扫描工具,能够帮助我们识别代码结构存在的问题。主要包括: 布局性能(以前是layoutopt工具,可以解决无用布局、嵌套太多、布局太多) 未使用到资源 不一致的数组大小 国际化问题(硬编码) 图标的问题(重复的图标,错误的大小) 可用性问题(如不指定的文本字段的输入型) manifest文件的错误 命令行用法 lint是命令工具,在SDK 的tools/ 目录下: $ lint /src/ 可以通过添加 --disable argument,禁用一个特定的检查,或一列的检查,例如: $ lint --disable MissingTranslation,UnusedIds,Usability:Icons /src/ 可以通过--check标志指定运行哪些确切的检查。这让你可以在代码库中查找一个具体的问题,比如: $ lint --check MissingPrefix /src/ 使用--show命令加上 id 列表或类别 (或不带参数查看全部)可以获取指定的问题的解释: $ lint --show MissingPrefix 要生成 HTML 报告,只需要添加--html文件名作为参数: $ lint --html /tmp/report.html 运行lint --help以获取可用参数的相关信息。 更多 http://developer.android.com/tools/help/lint.html 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/4783337.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

[React-Native]环境配置&amp;amp;HelloWorld

一、前言 手头有mac、有开发者证书,不想浪费资源,之前做过iOS开发,还会对移动开发表示关注,现在移动开发目前用Rect Native也是一个热潮,加上之前有web开发经验,然后就有了学习的冲动。Keep learning, make me happy! 二、环境配置 需要mac设备 需要Xcode6.3版本以上 安装Node.js:https://nodejs.org/download/ 建议安装watchman,终端命令:brew install watchman 安装flow:brew install flow 三、Hello,React-Native 现在我们需要创建一个React-Native的项目,因此可以按照下面的步骤: 打开终端,开始React-Native开发的旅程吧。 1. 安装命令行:sudo npm install -g react-native-cli 2. 创建HelloWorld项目:react-native init HelloWorld 3. 找到创建的HelloWorld项目,双击HelloWorld.xcodeproj即可在xcode中打开项目。xcodeproj是xcode的项目文件。 4. 在xcode中,使用快捷键cmd + R即可启动项目。基本的Xcode功能可以熟悉,比如模拟器的选择等。 5. 启动完成你应该会看到运行效果 四、初识HelloWorld工程 Xcode里面的代码目录结构暂时不用管了,打开HelloWorld项目文件夹,找到index.ios.js文件。 index.ios.js文件就是React-Native JS 开发之旅的入口文件了。 先来个感性的认识,修改一 些文本,下一篇会解读里面的代码。用文本编辑器打开index.ios.js文件。 (1)找到代码部分: <Text style={styles.welcome}> Welcome to React Native! </Text> 修改成 <Text style={styles.welcome}> React-Native入门学习 </Text> (2)修改welcome标签的样式 welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, 修改成: welcome: { fontSize: 20, textAlign: 'center', margin: 10, color: 'red', }, (3)如果有前端开发经验这些应该很容易理解,然后重新运行看效果 五、理解怎么运行到js脚本里面的 恭喜你 如果不搞懂上面这一个原理,参考学习官网的话你会发现第一个例子你就跑不起来,然后就会郁闷了。 六、运行官网的一个HelloWorld案例 在上面的基础上,我们来学习官网的案例。我们通过命令创建出来的HelloWorld有点复杂,我们可以删除重新写一个简单的HelloWorld开始。 参考官网第一篇教程 import React, { Component } from 'react'; import { AppRegistry, Text } from 'react-native'; class HelloWorldApp extends Component { render() { return ( <Text>Hello world!</Text> ); } } AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp); 如果你只是复制到index.ios.js文件中会出现报错,因为程序启动的时候找不到这个文件中的注册的HelloWorldApp类 修改: AppRegistry.registerComponent('HelloWorld', () => HelloWorldApp); 然后cmmand+d重新Reload即可,不需要重启应用,这也意味着React Native开发应用可以热更新 提示:隐藏状态栏 这里我们没有设置文本都位置,默认就是在左上角,会跟状态栏重叠,我们可以隐藏状态栏即可 运行效果 七、真机调试 网上好多文章讲述如何iOS真机调试,但都有问题,编译会报错,后来发现可能是版本不一致,我用的是目前最新版本0.40, (1)修改Signing (2)修改IP 真机运行效果:

优秀的个人博客,低调大师

Openstack 中的消息总线 &amp;amp; AMQP

目录 目录 消息总线 消息总线的原理 AMQP 消息总线 Openstack 采用了面向服务的开发模式(有别于面向对象和面向过程),需要我们去考虑各个服务之间和各项目之间是如何传递消息的。 Restful API:项目之间的通信。 消息总线:项目内部的服务之间的通信。 使用这种架构模式的好处在于:保证了各个项目对外提供服务的 API 接口可以被不同的客户端类型所调用。即,只要可以调用这个 API 接口,那么 Client 是使用什么技术来实现,Service 都不会受到影响,也不需要作出改变。Server 和 Client 做到了模块化的分离。除此之外,还能够保证项目内部通信接口的可扩展性和可靠性,可以支持大规模的部署。 消息总线:可以实现一些服务向总线发送信息,其他的服务从总线上获取消息的效果。就类似于回转寿司的回转带,所有人都可以往回转带上放寿司和取寿司,这样的话只需要有足够的位置,就能够随时加入或减少客人,而且并不会影响整个寿司店的运作。 消息总线的原理 项目内部各服务进程之间的通信使用了:oslo.messaging库所提供的函数方法。同时还需要以下两种技术作为支撑。 远程过程调用 RPC:一个服务进程可以调用其他远程服务进程的方法。调用的方式: call():远程方法会被同步执行,调用者会被阻塞直到返回方法的结果,在一些调用时间较长的场合中使用会对效率又很大的影响。( call() 调用的远程服务的方法会被马上执行,在执行的过程中还会把调用者的进程阻塞掉,知道返回结果为止。) cast():远程服务的方法会被异步执行,调用者不会被阻塞,结果也无须立即返回,可以在一个合适的时机(人为干预)去执行并返回结果。所以也要求调用者利用其他的方法来查询这次远程调用的结果。 事件通知:某一个服务进程将事件通知发送到消息总线上,所有在消息总线上且对该事件通知感兴趣的服务进程都可以将该事件通知获取并进行处理,执行的结果并不需要返回给事件发送者。这种方式不仅可以在项目组件内部的进程服务通信间实现,还可以在项目之间的通信中实现(EG. Ceilometer)。 AMQP AMQP高级消息队列协议:是一个基于应用层的,用于异步消息传递的协议规范。其功能包括了: 消息的导向/ 消息的队列/ 消息的路由/ 消息的可靠性/ 消息的安全性。不同的AMQP实现方式之间可以通过定义消息在网络上传输时的字节流格式来进行互相操作。 在一个实现了 AMQP协议 的中间件消息队列服务中,如:RabbitMQ。当由生产者发出的不同的消息被发送到 RabbitMQ Server 中的 Queue 时,RabbitMQ 会根据不同的条件把 Queue 中的请发传递给不同的消费者。如果消费者无法接收,那么这个消息,就会自动的把消息缓存在内存或者磁盘中。这些操作是由 RebbitMQ 中的 Exchange 和 Queue 来实现的( Exchange或Queue的数量不定 ): Excange(信息交换):决定了消息的路由转发,根据接收到的消息中的 Info (从消息属性/消息头/消息体中提取)来与绑定表匹配(消息的 routing key 和 Queue 的 binding key 匹配)以此来决定将消息转发到哪一个 Queue 中,然后消费者再从 Queue 中获取消息并进行处理。 Queue(消息队列):作为 消息存储 和 分发 实体,负责将消息缓存在内存或者磁盘中,并且按照一定的顺序将这些消息分发给一个或多个消费者。 注:Excange 负责将消息转发到 Queue 中,转发的判断依据是从消息中获取的routing key 与 Queue 中的 binding key 匹配结果。

优秀的个人博客,低调大师

Docker 搭建私有仓库Registry&amp;amp;Harbor

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36367789/article/details/81623854 为什么要弄私有仓库,大多是为了速度,我们再私有仓库中的push和pull的速度是特别快的。 利用registry快速搭建 /registry/”>https://hub.docker.com//registry/ Run a local registry: Quick Version $ docker run -d -p 5000:5000 --restart always --name registry registry:2 Now, use it from within Docker: $ docker pull ubuntu $ docker tag ubuntu localhost:5000/ubuntu $ docker push localhost:5000/ubuntu 这是官方的一个小demo。下面是我自己的实践。 # 拉取registry2.0版本 [root@FantJ ~]# docker pull registry:2 Trying to pull repository docker.io/library/registry ... 2: Pulling from docker.io/library/registry 81033e7c1d6a: Pull complete b235084c2315: Pull complete c692f3a6894b: Pull complete ba2177f3a70e: Pull complete a8d793620947: Pull complete Digest: sha256:672d519d7fd7bbc7a448d17956ebeefe225d5eb27509d8dc5ce67ecb4a0bce54 Status: Downloaded newer image for docker.io/registry:2 # 后台启动运行 [root@FantJ ~]# docker run -d -p 5000:5000 --restart always --name registry registry:2 ce5b8bfa6d7f535906730ea3a058b00e7cfdaaa20ea0db3c49d700a4e2c8a645 [root@FantJ ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/openjdk 8-jre bef23b4b9cac 2 weeks ago 443 MB docker.io/fantj/nginx latest ae513a47849c 4 weeks ago 109 MB docker.io/nginx latest ae513a47849c 4 weeks ago 109 MB docker.io/registry 2 d1fd7d86a825 4 months ago 33.3 MB # tag 镜像 [root@FantJ ~]# docker tag docker.io/nginx 127.0.0.1:5000/nginx # 上传到私有仓库 [root@FantJ ~]# docker push 127.0.0.1:5000/nginx The push refers to a repository [127.0.0.1:5000/nginx] 7ab428981537: Pushed 82b81d779f83: Pushed d626a8ad97a1: Pushed latest: digest: sha256:e4f0474a75c510f40b37b6b7dc2516241ffa8bde5a442bde3d372c9519c84d90 size: 948 [root@FantJ ~]# 缺点:没有可视化管理工具,私有仓库服务宕机造成麻烦,没有用户管理机制、没有操作的记录功能。 优点:搭建操作简单 利用harbor搭建 下载地址:https://storage.googleapis.com/harbor-releases/release-1.5.0/harbor-offline-installer-v1.5.1.tgz wget https://storage.googleapis.com/harbor-releases/release-1.5.0/harbor-offline-installer-v1.5.1.tgz tar zxvf harbor-offline-installer-v1.5.1.tgz cd harbor 修改配置harbor.cfg hostname = fantj.top:8888 http还是https啥的自己看着改 保存退出,直接运行install.sh cd .. ./install.sh 注意一点:harbor默认会占用80端口,所以请确保你的80端口不被占用,那怎么修改呢? 修改配置docker-compose.yml(需要改端口再进行) 将80:80的第一个80改为自定义的端口号 我在这里改成8888端口。 然后运行install.sh ...... [Step 4]: starting Harbor ... Creating network "harbor_harbor" with the default driver Creating harbor-log Creating redis Creating registry Creating harbor-db Creating harbor-adminserver Creating harbor-ui Creating nginx Creating harbor-jobservice ----Harbor has been installed and started successfully.---- Now you should be able to visit the admin portal at http://fantj.top:8888 . For more details, please visit https://github.com/vmware/harbor . 好的,成功了,我们来访问一下。 默认账号密码: admin Harbor12345 如果想修改,去harbor.cfg修改。 [root@FantJ harbor]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ea66b87c5d26 vmware/harbor-jobservice:v1.5.1 "/harbor/start.sh" 7 minutes ago Up 7 minutes harbor-jobservice 5fecbc47ea68 vmware/nginx-photon:v1.5.1 "nginx -g 'daemon ..." 7 minutes ago Up 7 minutes (healthy) 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:8888->80/tcp nginx 9ccfa0d137de vmware/harbor-ui:v1.5.1 "/harbor/start.sh" 7 minutes ago Up 7 minutes (healthy) harbor-ui b1f6387545d6 vmware/harbor-db:v1.5.1 "/usr/local/bin/do..." 7 minutes ago Up 7 minutes (healthy) 3306/tcp harbor-db 6bcd46635374 vmware/registry-photon:v2.6.2-v1.5.1 "/entrypoint.sh se..." 7 minutes ago Up 7 minutes (healthy) 5000/tcp registry c40db866f7d2 vmware/harbor-adminserver:v1.5.1 "/harbor/start.sh" 7 minutes ago Up 7 minutes (healthy) harbor-adminserver 8d0ee20abfbf vmware/redis-photon:v1.5.1 "docker-entrypoint..." 7 minutes ago Up 7 minutes 6379/tcp redis 17c002dd8b98 vmware/harbor-log:v1.5.1 "/bin/sh -c /usr/l..." 7 minutes ago Up 7 minutes (healthy) 127.0.0.1:1514->10514/tcp harbor-log [root@FantJ harbor]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE vmware/redis-photon v1.5.1 19245c7a4f51 3 days ago 207 MB vmware/clair-photon v2.0.1-v1.5.1 e7f0ab982469 3 days ago 303 MB vmware/notary-server-photon v0.5.1-v1.5.1 611385e920c3 3 days ago 211 MB vmware/notary-signer-photon v0.5.1-v1.5.1 f9e01495db0e 3 days ago 209 MB vmware/registry-photon v2.6.2-v1.5.1 2efae6b250b1 3 days ago 198 MB vmware/nginx-photon v1.5.1 90d35cd72a68 3 days ago 135 MB vmware/harbor-log v1.5.1 67000769dfac 3 days ago 200 MB vmware/harbor-jobservice v1.5.1 3f7a7987ca5b 3 days ago 194 MB vmware/harbor-ui v1.5.1 8dbe945233a8 3 days ago 212 MB vmware/harbor-adminserver v1.5.1 a11b8eb3f9d8 3 days ago 183 MB vmware/harbor-db v1.5.1 afa780d73279 3 days ago 526 MB vmware/mariadb-photon v1.5.1 59ed57632415 3 days ago 526 MB vmware/postgresql-photon v1.5.1 41b693c0ce50 3 days ago 221 MB docker.io/openjdk 8-jre bef23b4b9cac 2 weeks ago 443 MB vmware/harbor-migrator v1.5.0 466c57ab0dc3 4 weeks ago 1.16 GB 127.0.0.1:5000/nginx latest ae513a47849c 4 weeks ago 109 MB docker.io/fantj/nginx latest ae513a47849c 4 weeks ago 109 MB docker.io/nginx latest ae513a47849c 4 weeks ago 109 MB vmware/photon 1.0 4b481ecbef2a 5 weeks ago 130 MB docker.io/registry 2 d1fd7d86a825 4 months ago 33.3 MB 可以看到我们的进程和镜像都多了很多的以vmware开头的(harbor是vmware公司的开源工具). 好了,开始push测试 [root@FantJ harbor]# docker tag docker.io/nginx fantj.top:8888/internet-plus/nginx [root@FantJ harbor]# docker push fantj.top:8888/internet-plus/nginx The push refers to a repository [fantj.top:8888/internet-plus/nginx] Get https://fantj.top:8888/v1/_ping: dial tcp: lookup fantj.top: no such host 它提示需要用https请求才安全,解决方式有两种: 第一种:docker启动的时候添加对域名+端口的信任 –insecure-registry=xxxx.xx.xx.xx:8888 第二种:添加ssl证书,改天更新 Harbor重启 #docker-compose stop # ./install.sh 遇到过的问题 如果你的服务上挂了https,也就是SA证书,它和docker的harbor会有冲突,因为你访问的harbor端口会被

优秀的个人博客,低调大师

C# 内存分配&amp;&amp;垃圾回收解析

在学习C#的过程中,大家一定会听说过一些CLR、JIT、LR、什么堆栈分配、内存释放的东西,谈到大家对这些元素的理解,多数都是这些是操作系统里面的东西,值类型、引用类型会和堆栈相关,但是在问到这些提到的名称具体是做什么的,或者扮演什么样的角色的时候,大家好像也能讲出点什么,但是也讲得模模糊糊,虽然这些都是一些理论知识,而且在开发的过程中可能也用不到,但还是能尽量多了解一下比较好,今天,笔者就谈一谈自己对这些元素的理解 有说的不准确或者不正确的地方欢迎留言指正 在日常生活中,如果要和其他语种的人交流,而且自己还不懂得情况下我们会怎么办?首先会想到找翻译软件,首先把自己说的话输入到翻译软件中,软件会根据输入文字的语法转到另一种歪果仁说的语言,其中主要步骤会经过检测-----校验-----输出。 其实在计算机的世界中,代码编译成0101这种形式的机器码也是大概如此,首先我们会在编译器中(例如:visual studio 2017)根据逻辑的需求编写C#代码,这个可以理解为我们说的母语,然后经过计算机的翻译编译成机器能听懂的语言(机器码),而下图中显示的 【metadata】【IL】【CLR】【JIT】就是在上面举例中提到翻译,翻译过程中【检测】----【校验】----【输出】需要这些元素的参与 缩写的全称: CTS是通用类型系统(Common Type System) CLR是公共语言运行时(Common language runtime) CLS是公共语言定义(Common Language Specification) 参考链接:https://blog.csdn.net/huang_xw/article/details/8578162 参考链接:https://docs.microsoft.com/zh-cn/dotnet/standard/common-type-system 代码编译后会形成DLL或者EXE文件,在这些文件中含有【metadata】与【IL】两种元素,下面我们逐一说明这两个元素的用途 metadata 通俗的讲:metadata就是一个档案库,一份清单,一个说明里面含有什么东西的列表。他里面详细的说明这个DLL或者EXE文件中都有什么类、函数、属性、字段、版本号等等,而且经常用到的特性(Attribute)的信息也在里面,不熟悉【特性】的小伙伴请看Unity C#基础之 特性,一个灵活的小工具。(也就是举例中需要翻译的是什么语言,多少个字,含有什么标点符号,在什么位置等等这些信息) IL(中间语言) IL又称:中间语言,他在翻译过程中是起到牵线搭桥的作用,类似于我能听懂(编译器),歪果仁也能听懂(计算机)的语言。如果想查看IL可以使用ILSpy反编译工具查看 上面提到的【metadata】【IL】仅仅是翻译前的准备工作,下面才是开始正式的【检测】----【校验】----【输出】 首先说下CLR 说道CLR他就厉害了,正是因为有了CLR这种运行环境,才能让不同语言编译的IL得以在不同的操作系统中运行,例如32位、64位的操作系统,而且不同的操作系统里面额CLR也是不一样的。 然后是JIT 基于上面提到的CLR环境,JIT根据不同的CLR将相同的IL依据清单(metadata)和dll或exe,开始正式的【检测】----【校验】----【输出】生成0101这种的机器码,JIT编译的时候会检测是否编译过机器码。如果编译过拿过来复用 上面说到的整体流程可以看一下托管执行过程 接下来说一下.NET 中的内存管理和垃圾回收 因为下面所提到的都是总结性结论,参考地址MSDN官方文档 .NET 中的内存管理和垃圾回收 什么是“托管代码”? 自动内存管理 线程栈:栈-stack 先进后出的数据结构 随着线程而分配的 默认执行方法分配1MB内存 对象堆:内存,进程中独立画出来的一块儿内存,有一些对象长期使用不释放的,例如static,方便对象重用(多个对象指向一个内存地址) 我们结合代码来说一下堆栈的分配 public struct ValuePoint// : System.ValueType 结构不能有父类,因为隐式继承了ValueType(通过反编译工具可查看) { public int x; public ValuePoint(int x) { this.x = x; } } public void Test() { //内存分配:线程栈 {//值类型分配在线程栈,变量和值都是在线程栈 ValuePoint valuePoint;//先声明变量,没有初始化 但是我可以正常赋值 跟类不同 valuePoint.x = 123; ValuePoint point = new ValuePoint(); Console.WriteLine(valuePoint.x); } } 声明的valuePoint和他对应的x都是在栈上面的 public class ReferencePoint { public int x; public ReferencePoint(int x) { this.x = x; } } public void Test() { ReferencePoint referencePoint = new ReferencePoint(123); } 引用类型分布在堆上面 变量是在栈上的(保存的地址),值是在堆上面 new的时候去堆开辟内存,分配一个地址 调用构造函数(因为在构造函数里可以使用this),才执行构造函数把引用传给变量 /// <summary> /// class 引用类型 /// </summary> public class ReferenceTypeClass { private int _valueTypeField;//堆:因为对象都在堆里,对象里面的属性也在堆里 public ReferenceTypeClass() { _valueTypeField = 0; } public void Method() { int valueTypeLocalVariable = 0;//栈:全新的局部变量,线程栈来调用方法,然后分配内存 } } public void Test() { ReferenceTypeClass referenceTypeClassInstance = new ReferenceTypeClass(); referenceTypeClassInstance.Method(); } _valueTypeField是在堆上面,因为对象都在堆里,对象里面的属性也在堆里 valueTypeLocalVariable是在栈上面,因为全新的局部变量,线程栈来调用方法,然后分配内存 /// <summary> /// 值类型 /// </summary> public struct ValueTypeStruct { private object _referenceTypeField;// 这个对象的变量在栈上,值在堆上 public ValueTypeStruct(int x) { _referenceTypeField = new object(); } public void Method() { object referenceTypeLocalVariable = new object();//这个对象的变量在栈上,值在堆上 } } public void Test() { ValueTypeStruct valueTypeStructInstance = new ValueTypeStruct(); valueTypeStructInstance.Method(); } _referenceTypeField这个对象的变量在栈上(保存地址),值在堆上 referenceTypeLocalVariable这个对象的变量在栈上(保存地址),值在堆上 综上所述: 方法的局部变量:根据变量自身决定,跟所在的环境没关系 对象是引用类型,其属性/字段,都是在堆里面 对象是值类型,其属性/字段,值类型就在栈里 引用类型就在堆里 引用类型任何时候都在堆里;值类型都在栈里, 除非值类型所在对象是在堆里(ReferencePoint这个例子就是) 装箱和拆箱(C# 编程指南) { int i = 0; object oValue = i; i = (int)oValue; } 装箱拆箱(仅仅是说内存的拷贝动作):内存copy 也会浪费性能 通常都是因为object 装箱拆箱只能发生在父子类里面, 否则无法转换 string字符串内存分配 string student = "菜鸟海澜";//开辟一块儿内存 放入“菜鸟海澜“ 返还一个引用(student变量) string student2 = student;//把student的引用copy一份儿给student2 Console.WriteLine(student);//打印结果 菜鸟海澜 Console.WriteLine(student2);//打印结果 菜鸟海澜 student2 = "菜鸟"; Console.WriteLine(student);//打印结果 :菜鸟海澜 Console.WriteLine(student2);//打印结果:菜鸟 改了student2的值 但是不是修改内存;因为string字符串的内存是不可变的 赋值其实是new string(APP),重新开辟内存,返回引用 不可变是因为享元,可能有多个变量指向同一个字符串,字符串变化了,多个变量都会受到影响。(例如多个类中的不同字符串变量都声明 "菜鸟海澜",本质上都是指向一个地址) 还因为堆里面的内存是连续分配的,如果变长度,会导致大量数据的移动 string student = "菜鸟海澜"; string student2 = "菜鸟";//共享 student2 = "菜鸟海澜"; Console.WriteLine(object.ReferenceEquals(student, student2));//打印结果为 True 就是同一个 享元模式 CLR内存分配字符串的时候,会查找相同值,有就重用了 使用享元的主要原因: 因为在堆中每个对象的内存都是紧密连接的,使用享元且不可改变,这样可以提高内存的使用率。 避免导致大量数据的移动,降低内存的重新分配、摆放(有不同的线程栈,但共用一个堆)。 垃圾回收 参考自 垃圾回收 与 清理非托管资源 网上一位开发者的文章:https://kb.cnblogs.com/page/106720/ 首先简述一下线程栈和托管堆的概念 值类型出现在线程栈:每次调用都有线程栈,,用完自己就结束,变量-值类型 都会释放的(不用我们维护) 引用类型出现在堆里:全局就一个堆,空间有限,所以才需要垃圾回收 操作系统里面,内存是链式分配的,可能有碎片的 CLR的堆:连续分配(数组),空间有限,节约空间 大对象策略:如果该对象占用内存大于85000字节,属于大对象,单独管理,用的是链表(碎片),避免频繁的内存移动造成性能消耗 下面要说的垃圾回收主要是以堆中的操作为主要内容 GC(Garbage Collector 的缩写) 1问:什么是垃圾? 垃圾是完全访问不到的东西了。例如临时变量,或者已经赋值为null的引用类型的变量 2问:什么时候会发生GC? gc发生在new的时候 new一个对象时,会开辟内存,看看空间够不够,不够的话就要GC了 gc程序退出的时候也会gc 手动GC。例如定时程序,很久执行一次,而且使用的时长很短,这时候就可以手动GC了 3问:怎么回收? new的时候发现内存不够,然后就去遍历所有堆的对象,标记有引用的对象,然后启动一个线程来清理内存 清除没有标记的对象,挪动其他剩余对象,然后整齐摆放,所以这个时候全部线程停止(开多线程时这个时候是停止的),不允许操作内存 内存不够的是指一级对象的内存,有个临界值,也不是全部的堆的大小 但是类中含有 析构函数【~类名称()】 ,内存的释放就需要单独的处理,把这些对象放入一个队列单独处理,具体哪一时刻调用析构函数不确定 注意:静态的对象是不会被回收的,且持有的引用也是不会被回收的 关于垃圾回收第几代的问题官方文档是这么说明的 在下面的例子中,声明一个静态变量staticStudent ,调用Test方法后主动调用GC,最终 变量【student】【@class】会被回收,但他们对应在堆中的内容不会被回收,因为有staticStudent 持有,变量 【i】会在弹栈之后直接被回收,变量【gCTest】以及它对应在堆中的内容都会被回收 private static Student staticStudent = new Student()//静态的不可能被回收 静态持有的引用也不会被回收 { Id = 123, Name = "菜鸟海澜" }; public void Test() { Student student = staticStudent; Class @class = new Class() { classId = 1, classdata = "数据" }; student.tempdata = @class; int i = 0;//都会被GC GCTest gCTest = new GCTest();//都会被GC } 在下面的示例中,很多开发者会把一个非静态变量设置成null,其实编译器会无视这句话,不是改成null这个对象没有了,其实内存还占用着,把对象赋值成null 意义不大,垃圾回收主要的原因是因为访问不到。但是静态可以把变量设置成null,促进垃圾回收,这样可以让变量不再被引用 Student student = new Student() { Id = 1, Name = "su9257", tempdata = new Class() { classId = 1, classdata = "数据1" } }; student = null; GC.Collect(); 非托管资源的释放 关于释放非托管资源必须要谈到的两个东西:【析构函数】和【Disposable】 析构函数 析构函数 主要是用来释放非托管资源(函数中调用具体释放资源的API或方法),等着GC的时候去把非托管资源释放掉 系统自动执行 GC回收的时候,CLR一定调用的,但是可能有延迟,具体是哪个时刻不确定 Dispose Dispose() 也是释放非托管资源的,主动释放(或手动调用),方法本身是没有意义的,我们需要在方法里面实现对资源的释放 GC不会调用,而是用对象时,使用者主动调用这个方法,去释放非托管资源 不过Dispose有一个自动调用的方法,就是使用【using】关键字,在using语句块运行完时自动调用Dispose方法(前提有的情况下)。且在Dispose方法中调用GC.SuppressFinalize(this);就是告诉CLR这个类我要释放的东西已经释放完了,你就不用调用析构函数了 using (Student student = new Student()) { Console.WriteLine("菜鸟海澜"); } public class People : IDisposable { public string Remark { get; set; } public virtual void Dispose() { Console.WriteLine($"执行{this.GetType().Name}Dispose"); } } public class Student : People, IDisposable { public int Id { get; set; } public string Name { get; set; } public Class tempdata { get; set; } public override void Dispose()//提供主动释放方式 { base.Dispose();//把我引用的其他东西给清理掉 if (this.tempdata != null) { this.tempdata.Dispose(); } //通知垃圾回收机制不再调用终结器(析构器) GC.SuppressFinalize(this); } 本质上是调用try finally try { } finally { //调用的dispose() }

优秀的个人博客,低调大师

依赖注入 in 前端 &amp;&amp; Typescript 实现依赖注入

背景 最近因为工作需要,研究了vscode的代码,看文档时发现其中提到了Dependency Injection,并且在类的构造函数中看到了这样的写法。 constructor( id: string, @IMessageService messageService: IMessageService, @IStorageService storageService: IStorageService, @ITelemetryService telemetryService: ITelemetryService, @IContextMenuService contextMenuService: IContextMenuService, @IPa

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册