[Golang]两个对象的指针相同,一定是同一个对象吗?

<摘要>: 开门见山 今天发现一个十分有趣的case,如下: package main import "fmt" func main() { n1 := make ([] int, 0,5) n2 := n1[:2] fmt.Println(n1) fmt.Println(n2) // 思考 n1和n2打印出的指针地址是否相同? fmt.Printf("address of n1:%p\n",n1) fmt.Printf("address of n2:%p\n",n2) } n1不是指针类型,是make的一个[]int slice的引用类型,可能多数人会有这样的思考: 两个对象的指针地址相同,那么这两个对象存储的内容是相同的,即使slice的底层数组结构SliceHeader的Data字段域(数组),在未超出n1的容量5之前,和n2用的是一个Data字段域,但是因为sliceHeader里第二个字段域是Len,第三个是Cap,n1和n2的SliceHeader肯定不是同一个,那么用%p打印出的指针地址肯定是不同的指针地址,我开始也是这样的想法,然后结果让我大吃一惊, 如下: [] [0 0] address of n1:0xc00007e030 address of n2:0xc00007e030 什么? 打印出的指针地址相同。我瞬间就不淡定了 这似乎颠覆了我的一个固定观念–两个对象的指针地址相同,那么这两个对象存储的内容是相同的 猜想 带着自己的疑惑 我首先想到的是利用反射,把slice转成SliceHeader来一探究竟 看看Data,Len,Cap三个字段域是否相同: package main import ( "fmt" "reflect" "unsafe" ) func main() { n1 := make ([] int, 0,5)   Read more

Author anteoy@gmail.com | Posted 2020-01-11 8:33:20 | Tags golang,slice,append,%p,指针

java golang tcp socket导致线上服务器出现大量close_wait的完整示例

<摘要>: tcp断开连接的四次挥手 先说说tcp的四次挥手,这里假定A端为主动发起关闭端,B端为被动接收关闭请求端。A把tcp的数据包中标识位FIN置为1,seq为一个随机数,发送这个包给B端,自己进入FIN_WAIT_1状态;B端收到了马上给A端回复ack(A端收到ack进入FIN_WAIT_2状态),然后自己进入CLOSE_WAIT状态。然后这个时候需要业务代码处理,把自己需要发给客户端的数据发送完,然后业务代码主动调用相应语言库函数提供的close函数,来触发关闭操作:给A端发送FIN seq的数据包,这是第三次握手。这个时候自己进入last ack状态。 A端此时收到包然后给B端口发送相应ack.A端自己此时进入time_wait状态。 B端收到ack后从last_ack就顺利进入close状态了。A端等到timewait 2msl时间后(这个时间不同的操作系统的设置不同,大约是2分钟),自动进入close状态。 如果在B端不主动调用相应自己语言的close函数,那么就会一直处于close wait状态。大量socket连接不能正常释放。直到socket服务器端打开的文件数超过系统的最大限制数,其他连接无法正常建立连接,建立连接的时候抛出too many open files异常 网上搜索的图,便于理解(侵删) linux 统计tcp连接的各种状态的连接数 这里每5秒输出一次 可以修改为自己想要的时间 while true ;do netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' && print '-------------' ; sleep 5; done; java版本的完整复现代码 只需要把Server.java中socket.close();  Read more

Author anteoy@gmail.com | Posted 2019-05-21 12:33:20 | Tags java,string,golang,socket,close_wait

Java IO流源码笔记

<摘要>: 概览 Java中的IO源为4个抽象类,2个字节流相关抽象类InputStream,OutputStream. 2个字符流相关抽象类Reader,Writer.直接联系是都实现了Closeable接口,另外,整个IO的代码基于装饰者模式设计,存在大量的组合 > 聚合 > 关联 > 依赖关系,不了解UML模型图和关系的可以点击这里快速了解。我这里为了UML图的可读性,没有打开dependencies。有兴趣的读者可以自己使用IDEA的diagrams功能查看 除了抽象类Reader下面的FilterReader是抽象类,其他实现全部是非抽象类。包括缓冲Buffered,数据Data,文件File,字节数组ByteArray,Object,String等各种字节/字符流实现类 IO实现类中分为两类,一类是被装饰者类,一类是装饰者。被装饰者类就是能够从数据源获取数据的类,比如网络,文件,标准输入/输出等,另一类型是装饰者类,比如BufferedInputStream/BufferedOutputStream等,装饰者类中依赖一个数据源被装饰者类,来实现特定功能,比如缓冲的流读写等,体现在装饰者类的构造函数中需要传入一个被装饰的数据流 字节流抽象类约定的需实现的抽象方法read()返回的是int,即ASCII,而字符流约定需要实现的抽象方法为abstract public int read(char cbuf[], int off, int len) throws IOException;读取字符数据到字符数组cbuf中,返回读取到的字符数int InputStream-被装饰者超类 package java.io; /** * 此类只有一个抽象方法 read() 所有继承此类的方法必须实现read()方法 用于从输入流中处理读取数据的过程 */ p  Read more

Author anteoy@gmail.com | Posted 2019-04-11 19:03:20 | Tags java,string,源码

JDK常用设计模式整理

<摘要>: 观察者模式 jdk中有提供接口Observer 和用于定义subject的类Observable subject.addObserver(new ObserveTest()); subject.set(3); subject.setChanged(); subject.notifyObservers(3); subject持有一个Vector(线程安全的list),用于存储addObserver方法里面添加的观察者Observer,通知通过Observer的update方法进行更新 桥接模式 主要关注桥 先有桥 然后桥两边可以独立变化扩展 比如jdk里面的 Set names = Collections.newSetFromMap( new ConcurrentHashMap() ); 把set和map桥接起来,同时map和set都可以独立扩展和变化 装饰者模式Decorator 每个Decorator均有一个指向Subject对象的引用,附加的功能被添加在这个Subject对象上,不改变原始的指向类。而Decorator对象本身也是一个Subject对象,因而它也能够被其他的Decorator所修饰,提供组合的功能。 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) while(true){ System.out.println(br.readLine()) } BufferedReader InputStreamReader 都继承了抽象类Reader,然后BufferedReader类里持有InputStreamReader对象的引用 两个都是独立的  Read more

Author anteoy@gmail.com | Posted 2019-04-11 14:53:20 | Tags java,设计模式

Java ThreadPoolExcutor源码笔记

<摘要>: 概要速记 接口Excutor->接口ExutorService->抽象类AbstractExcutorService->类ThreadPoolExcutor 线程达到上限策略corePollSize->blockQueue->maxPollSize->handle blockQueue参数如果使用LinkedBlockQueue则会使maxPollSize参数无效 此为无界队列 一般使用有界队列ArrayBlockQueue 有个参数设置核心线程外的keepalive time,超时线程会被销毁 ThreadPoolExecutor分析 部分字段分析 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); 使用Integer.SIZE - 3以及-1(-1的二进制表示,在计算机器的世界用补码表示的,除符号位按位取反再加1:11111111111111111111111111111111)进行位移得到的RUNNING的二进制为11100000000000000000000000000000 ctlOf是return RUNNING|0 所以ctl的初始值也为11100000000000000000000000000000 AtomicInteger是Java中使用CAS机制实现的保证原子操作的Integer类 查看类注释 ”` The main pool control state, ctl, is an atomic integer packing two conceptual fields workerCount, indicating the effective number of threads runState, indicating whether running, shutting down etc In order to pack the  Read more

Author anteoy@gmail.com | Posted 2019-04-11 14:03:20 | Tags java,string,源码

Java String源码笔记

<摘要>: 源码 实现了3个接口 Serializable Comparable CharSequence 关于CharSequence Java从String类和StringBuffer类开始。但是这两个类是无关的,没有通过继承和接口相互联系。后来,Java团队意识到字符串相关实现之间应该存在统一的联系,以使它们可以互换。在Java4中,团队添加了CharSequence接口并在String和String Buffer上追溯实现了该接口,并添加了另一个实现CharBuffer。后来在Java5中他们添加了一个不保证线程安全的,速度较快的实现:StringBuilder。 final class String是一个不可被继承的类 主要字段: private final char value[]; final 数组 数组指针不可变 值可变 用来存储实际的字符串值 private int hash; private static final long serialVersionUID = -6849794470754667710L; 序列化标识码 主要方法: String(String original) 构造函数 会复制传入的original,如果不需要复制orginal,则直接使用String s = “abc”就可以了,而不是用new String() 无参构造函数 会用”“.value来复制this.value,所以可以直接使用 String s = “”; 否则会在堆上像如上构造函数new出一个String对象 String(char value[]) {this.value = Arrays.copyOf(value,value.length)} 从char数组复制一个新的char数组赋予String的成员变量value String(char value[], int offset, int count) 主要是边界判断以及this.value = Arrays.copyOfRange(value, offset, offset+count); Stri  Read more

Author anteoy@gmail.com | Posted 2019-04-09 17:31:20 | Tags java,string,源码

java技术圈上线啦,欢迎常驻~~~

<摘要>: Java技术圈 一个开放,和谐,互帮互助,知识分享的IT技术社区。旨在为解决各种实际运用的技术问题和相关技术分享而成立的问答,知识分享社区。目前主要对标服务于Java,Golang,容器技术Docker,Kubernetes,以及机器学习相关生态 欢迎大家常驻 http://www.itsharecircle.com 进群送千G学习资料 微信扫描如下二维码(或者微信搜索用户Anteoy)添加我为好友,备注Java技术圈,我拉你进群 )   Read more

Author anteoy@gmail.com | Posted 2019-04-04 17:31:20 | Tags

java和golang中的unsafe包

<摘要>: 首先聊聊反射 java和golang都有各自的反射机制,为什么标准库会提供反射机制呢? 反射(reflection)允许程序在运行时(runtime)检查、修改程序(比如对象,struct等)的结构与行为,跳过编译检查,越过访问权限,运行时对象生成,方法调用等。如果没有反射,那么需要完全手动进行硬编码,比如如果没有反射,那么在spring的ioc容器管理实现就需要我们使用new来创建对象,那么也就不叫spring ioc,不会有spring ioc的诞生了。 静态编译(多数静态语言):在编译时确定类型,绑定对象。 动态编译(多数动态语言):运行时确定类型,绑定对象。可以实现动态创建对象和编译,体现出很大的灵活性(特别是在J2EE的开发中它的灵活性就表现的十分明显)。通过反射机制我们可以获得类的各种内容。对于java以及golang这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。 反射的实现 在java和golang的反射实现中,主要依赖于对象指针(也就是对象的内存地址),以及编译时已链接到对象上的强类型信息。 BTW,在java语言的反射Method.invoke方法调用实现中,默认为委派实现,委派给本地方法来进行方法调用。在调用超过15次之后,委派实现便会将委派对象切换至动态实现(自己动态生成字节码),动态实现和本地实现相比,其运行效率要快上20倍,因为本地实现需要先调c++本地实现,然后c++的返回再用java接收,所以是比较耗时的。另外,生成动态实现的字节码也是比较耗时的,当然生成动态调用的字节码只生成一次,生成后就可以多次调用。 为何需要unsafe 在golang的标准包中,提供了unsafe操作(unsafe.go),通过主要用于对内存指针的操作,普通对象指针通过转化为unsafe.Pointer,而unsafe.Pointer可以转化为uintptr,uintptr支持指针相关的内存操作,通过unsafe包,间接的实现了直接指针内存相关的操作. 而在java的标准包中,并没有提供unsafe包,unsafe包存在于sun.msic下的Unsafe.java类,misc即miscellaneo  Read more

Author anteoy@gmail.com | Posted 2019-03-22 17:53:50 | Tags java jvm 字节存储 中间件

浅析字节存储序列的大小端存储方式

<摘要>: 基础 内存地址是从低地址开始进行编号的,用16进制来进行编号,比如内存的开始地址(即低地址)0x0000,然后内存偏移以字节为单位,比如0x0001表示从0x0000位置偏移到后面1个字节,即偏移8bit.字节的高低位是俗成约定的,比如字节序列0x12345678,由于一个16进制的转为2进制占四个2进制(2^4=16,进制转换基础),那么0x12则可以转为8个二进制,也就是8bit=1byte,也就是1字节,回到字节的高低位的俗成约定,0x12为最高位,0x78为字节序列的最低位置 什么是大端和小端 Big-Endian和Little-Endian的定义如下: 1. Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。 2. Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。 举一个例子,比如数字0x12 34 56 78在内存中的表示形式为: - 大端模式: 低地址 —————–> 高地址 0x12  |  0x34  |  0x56  |  0x78 - 小端模式: 低地址 ——————> 高地址 0x78  |  0x56  |  0x34  |  0x12 具体例子 16bit宽的数0x1234在Little-endian模式(以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存存放的起始地址 小端模式存放内容 大端模式存放内容 0x0000 0x34 0x12 0x0001 0x12 0x34 32bit宽的数0x12345678在Little-endian模式以及Big-endian模式)CPU内存中的存放方式(假设从地址  Read more

Author anteoy@gmail.com | Posted 2019-03-22 11:22:50 | Tags java jvm 字节存储 中间件

速查jvm字节码指令

<摘要>: JVM指令集参考 0x00 nop 什么都不做 0x01 aconst_null 将null推送至操作栈栈顶 0x02 iconst_m1 将int型-1推送至操作栈栈顶 0x03 iconst_0 将int型0推送至操作栈栈顶 0x04 iconst_1 将int型1推送至操作栈栈顶 0x05 iconst_2 将int型2推送至操作栈栈顶 0x06 iconst_3 将int型3推送至操作栈栈顶 0x07 iconst_4 将int型4推送至操作栈栈顶 0x08 iconst_5 将int型5推送至操作栈栈顶 0x09 lconst_0 将long型0推送至操作栈栈顶 0x0a lconst_1 将long型1推送至操作栈栈顶 0x0b fconst_0 将float型0推送至操作栈栈顶 0x0c fconst_1 将float型1推送至操作栈栈顶 0x0d fconst_2 将float型2推送至操作栈栈顶 0x0e dconst_0 将double型0推送至操作栈栈顶 0x0f dconst_1 将double型1推送至操作栈栈顶 0x10 bipush 将单字节的常量值(-128~127)推送至操作栈栈顶 0x11 sipush 将一个短整型常量值(-32768~32767)推送至操作栈栈顶 0x12 ldc 将int, float或String型常量值从常量池中推送至操作栈栈顶 0x13 ldc_w 将int,float或String型常量值从常量池中推送至操作栈栈顶(宽索引) 0x14 ldc2_w 将long或double型常量值从常量池中推送至操作栈栈顶(宽索引) 0x15 iload 将指定的int型局部变量推送至操作栈栈顶 0x16 lload 将指定的long型局部变量推送至操作栈栈顶 0x17 fload 将指定的float型局部变量推送至操作栈栈顶 0x18 dload 将指定的double型局部变量推送至操作栈栈顶   Read more

Author anteoy@gmail.com | Posted 2019-03-13 18:56:00 | Tags java jvm