【字符编码】Java编码格式探秘

一、前言 在分析Comparable和Comparator的时候,分析到了String类的compareTo方法,String底层是用char[]数组来存放元素,在比较的时候是比较的两个字符串的字符,字符用char来存储,此时,突然想到,Java里面的char可以存放中文吗?后来发现是可以的,并且由此也引出了Java中字符的编码格式问题。 二、Java存储格式 在Java中,如下代码获取了字符'张'的各种编码格式。 import java.io.UnsupportedEncodingException; public class Test { public static String getCode(String content, String format) throws UnsupportedEncodingException { byte[] bytes = content.getBytes(format); StringBuffer sb = new StringBuffer(); for…

Continue Reading 【字符编码】Java编码格式探秘

【Linux】Linux学习笔记(完结)

前言 在工作中发现Linux系统的重要性,于是计划重温下Linux,顺便记录笔记方便之后查阅。 磁盘分区 在Linux系统中,每个设备都被当成一个文件来对待;如IDE接口的硬盘文件名为/dev/hd[a-d]。 磁盘的第一个扇区记录了主引导分区(MBR)和分区表;主引导分区可以安装引导加载程序的地方,有446bytes,系统开机时会主动读取MBR区块的内容;分区表记录硬盘分区状态,有64bytes。 磁盘分区是对分区表进行设置,默认分区表仅能写入四组分区信息,四组分区信息称为主或扩展分区。 使用扩展分区划分出来的为逻辑分区,其编号从5开始,如/dev/hda5/、/dev/hda6...。前四个分区号均保留。 主与扩展分区最多有4个``扩展分区最多只有1个,逻辑分区是由扩展分区分割出来的分区,只有主分区和逻辑分区能够被格式化,扩展分区不能。 若扩展分区被破坏,所有逻辑分区将会被删除。 BIOS是写入到硬件上的程序,其会根据用户设置取得能够开机的硬盘,并且到该硬盘下读取第一个扇区的MBR位置,MBR中存放了最基本的引导加载程序,接下来由引导加载程序(boot loader)加载内核文件,然后内核文件开始操作系统的功能。 引导加载程序主要提供三个服务: 提供菜单:可选择不同开机选项,是多重引导的重要功能。 载入内核文件:指向可开机的程序区段来开始操作系统。 转交其他loader:将引导加载功能转交给其他loader负责。 引导加载程序除了可以安装在MBR外,还可以安装在每个分区的引导扇区。 每个分区拥有自己的启动扇区,实际可开机的内核文件放置在各分区内,loader只认识自己系统分区内的可开机内核文件以及其他loader,loader可直接指向或间接将管理权转交给另一个管理程序。 系统登录 Linux默认提供6个Terminal供用于登录,切换方式为Ctrl+Alt+[F1-F6],名称分别为tty1-tty6,使用Ctrl+Alt+F7可切换至图形界面。 若以纯文本环境启动Linux,若想启动图形界面,可使用startx命令启动图形界面。 使用man + 命令可查看帮助,如man date。 使用shutdown命令关机,如shutdown -h now表示现在关机,shutdown -h 20:25表示20:25关机。 文件权限和目录配置…

Continue Reading 【Linux】Linux学习笔记(完结)

【大数据】Linux下安装Hadoop(2.7.1)详解及WordCount运行

一、引言 在完成了Storm的环境配置之后,想着鼓捣一下Hadoop的安装,网上面的教程好多,但是没有一个特别切合的,所以在安装的过程中还是遇到了很多的麻烦,并且最后不断的查阅资料,终于解决了问题,感觉还是很好的,下面废话不多说,开始进入正题。 本机器的配置环境如下: Hadoop(2.7.1) Ubuntu Linux(64位系统) 下面分为几个步骤来详解配置过程。 二、安装ssh服务 进入shell命令,输入如下命令,查看是否已经安装好ssh服务,若没有,则使用如下命令进行安装: sudo apt-get install ssh openssh-server 安装过程还是比较轻松加愉快的。 三、使用ssh进行无密码验证登录 1.创建ssh-key,这里我们采用rsa方式,使用如下命令: ssh-keygen -t rsa -P "" 2.出现一个图形,出现的图形就是密码,不用管它 cat ~/.ssh/id_rsa.pub >> authorized_keys(好像是可以省略的) 3.然后即可无密码验证登录了,如下: ssh localhost…

Continue Reading 【大数据】Linux下安装Hadoop(2.7.1)详解及WordCount运行

【字符编码】彻底理解字符编码

一、前言 在解决昨天的问题时,又引出了很多新的问题,如为什么要进行编码,这些编码的关系如何,如ASCII,IOS-8859-1,GB2312,GBK,Unicode之间的关系,笔者想要彻底理解字符编码背后的故事,遂进行了探索,具体笔记如下。如园友能读完本篇文章,我相信会解开很多疑惑。 二、字符编码 2.1 为何需要编码? 我们知道,所有的信息最终都表示为一个二进制的字符串,每一个二进制位(bit)有0和1两种状态。当我们需要把字符'A'存入计算机时,应该对应哪种状态呢,存储时,我们可以将字符'A'用01000010(这个随便编的)二进制字符串表示,存入计算机;读取时,再将01000010还原成字符'A'。那么问题来了,存储时,字符'A'应该对应哪一串二进制数呢,是01000010?或者是10000000 11110101?说白了,就是需要一个规则。这个规则可以将字符映射到唯一一种状态(二进制字符串),这就是编码。而最早出现的编码规则就是ASCII编码,在ASCII编码规则中,字符'A'既不对应01000010,也不对应1000 0000 11110101,而是对应01000001(不要问为什么,这是规则)。 2.2 ASCII 这套编码规则是由美国定制,一共规定了128个字符的编码,比如空格"SPACE"是32(十进制)(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括 32个不能打印出来的控制符号),只占用了一个字节(8 bit)的后面7位,最前面的1位统一规定为0。总共才有128个字符编码,一个字节都没有用完,这好像似乎有点太少了。于是乎,就开始压榨最高位,对其为1时也进行编码,利用最高位进行编码的方式就称为非ASCII编码,如ISO-8859-1编码。 2.3 ISO-8859-1 这套编码规则由ISO组织制定。是在 ASCII 码基础上又制定了一些标准用来扩展ASCII编码,即 00000000(0) ~ 01111111(127) 与ASCII的编码一样,对 10000000(128) ~ 11111111(255)这一段进行了编码,如将字符§编码成 10100111(167)。ISO-8859-1编码也是单字节编码,最多能够表示256个字符。Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。但是,即使能够表示256个字符,对中文而言,还是太少了,一个字节肯定不够,必须用多个字节表示。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用 ISO8859-1编码来表示。而且在很多协议上,默认使用该编码。比如,虽然"中文"两个字不存在ISO8859-1编码,以GB2312编码为例,应该是D6D0 CEC4两个字符,使用ISO8859-1编码的时候则将它拆开为4个字节来表示:D6D0 CEC4(事实上,在进行存储的时候,也是以字节为单位进行处理)。而如果是UTF编码,则是6个字节e4…

Continue Reading 【字符编码】彻底理解字符编码

【目录】JVM目录

1. 【JVM】JVM系列之JVM体系(一) 2. 【JVM】JVM系列之垃圾回收(二) 3. 【JVM】JVM系列之Class文件(三) 4. 【JVM】JVM系列之类加载机制(四) 5. 【JVM】JVM系列之执行引擎(五) 6. 【JVM】JVM系列之内存模型(六)

Continue Reading 【目录】JVM目录

【JVM】JVM系列之内存模型(六)

一、前言 经过前面的学习,我们终于进入了虚拟机最后一部分的学习,内存模型。理解内存模型对我们理解虚拟机、正确使用多线程编程提供很大帮助。下面开始正式学习。 二、Java并发基础 在并发编程中存在两个关键问题①线程之间如何通信 ②线程之间如何同步。 2.1 通信 通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信。 在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。 2.2 同步 同步是指程序用于控制不同线程之间操作发生相对顺序的机制。 在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥访问。 在消息传递的并发模型里,由于消息的发送必须在消息的接收之前, 因此同步是隐式进行的。 Java并发采用的是共享内存模型,通信隐式进行;同步显示指定。 三、Java内存模型 Java内存模型JMM(Java Memory Model)主要目标是定义程序中各个变量(非线程私有)的访问规则,即在虚拟机中将变量存储到内存和从内存取出变量这样的底层细节。Java中每个线程都有自己私有的工作内存。工作内存保存了被该线程使用的变量的主内存副本拷贝,线程对变量的读写操作都必须在工作内存进行,无法直接读写主内存中的变量。两个线程无法直接访问对方的工作内存。 3.1 线程、工作内存、内存关系 理解线程、主内存、工作内存之间的关系时,我们可以类比物理机中CPU、高速缓存、内存之间关系,学过计算机组成原理,我们知道CPU、高速缓存、内存之间的关系如下 线程、主内存、工作内存的关系图如下 说明:线程的工作内存可以类比高速缓存,JMM控可以类比缓存一致性协议,是工作内存与主内存进行信息交换的具体协议。若线程A要与线程B通信(访问变量)。首先,线程A把工作线程中的共享变量刷新到主内存中。然后,线程B从主内存读取更新过的变量。 3.2 内存间通信的指令 内存见通信,主要指线程私有的工作内存与主内存之间的通信,如线程间共享变量的传递。主要有如下操作。 说明:①变量从主内存放入工作内存变量副本中实际是分为两步的,第一步是先把主内存的值放在工作内存中,此时还没有放入变量副本中;第二部把已经放在工作内存的值放入变量副本中。相反,变量副本从工作内存到主内存也是分为两步,与前面类似,不再累赘。总之,两个内存空间的变量值的传递需要两个操作才能完成,这样做是为了提高cpu的效率,不等待主内存写入完成。②read、load操作;store、write操作必须按顺序执行(并非连续执行)。…

Continue Reading 【JVM】JVM系列之内存模型(六)

【JVM】JVM系列之执行引擎(五)

一、前言 在了解了类加载的相关信息后,有必要进行更深入的学习,了解执行引擎的细节,如字节码是如何被虚拟机执行从而完成指定功能的呢。下面,我们将进行深入的分析。 二、栈帧 我们知道,在虚拟机中与执行方法最相关的是栈帧,程序的执行对应着栈帧的入栈和出栈,所以栈帧对于执行引擎而言,是很重要的基础。栈帧的基本结构之前已经有所介绍,这里只是再简单的过一遍。 栈帧主要包括了局部变量表、操作数栈、动态连接、方法返回地址等信息。 2.1 局部变量表 用于存放方法参数和方法内部的局部变量。局部变量表的大小在方法的Code属性中就已经定义好了,为max_locals的值,局部变量表的单位为slot,32位以内的类型只占用一个slot(包括returnAddress类型),64位的类型占用两个slot。注意,对于实例方法而言,索引为0的slot存放的是this引用,之后再依次存放方法参数,定义的局部变量;slot可以被重用,当局部变量已经超出了作用域时,在作用域外在定义局部变量时,可以重用之前的slot空间。同时,局部变量没有赋值是不能够使用的,这和类变量和实例变量是有不同的,如下面代码: public void test() { int i; System.out.println(i); } 这样的代码是错误的,没有赋值不能够使用。 2.2 操作数栈 执行方法时,存放操作数的栈,栈的深度在方法的Code属性中已经定义好了,为max_stack的值,32位以内的类型占用一个栈单位,64为的类型占用两个栈单位。操作数栈可以与其他栈的局部变量表共享区域,这样可以共用一部分数据。 2.3 动态连接 动态连接是为了支持在运行期间将符号引用转化为直接引用的操作。我们知道,每一个方法对应一个栈帧,而每一个栈帧,都包含指向对应方法的引用,这个引用就是为了支持动态连接,如invokedynamic指令。动态连接与静态解析对应,静态解析是在类加载(解析阶段)或者第一次使用时将符号引用转化为直接引用,动态连接则是每一次运行的时候都需要进行转化(invokedynamic指令)。 2.4 方法返回地址 正常方法返回,返回地址为到调用该方法的指令的下一条指令的地址;异常返回,返回地址由异常表确定。方法返回时,需要恢复上层方法的局部变量表、操作数栈、将返回值压入调用者栈帧的操作数栈、设置PC值。 三、方法调用 在分析了栈帧后,我们接着分析方法调用,方法调用会导致栈帧入栈,而方法调用会确定调用哪一个方法,还不会涉及到具体的方法体执行。 3.1 解析…

Continue Reading 【JVM】JVM系列之执行引擎(五)

【JVM】JVM系列之类加载机制(四)

一、前言 前面分析了class文件具体含义,接着需要将class文件加载到虚拟机中,这个过程是怎样的呢,下面,我们来仔细分析。 二、什么是类加载机制 把class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是类加载机制。 三、类加载总体流程图 说明:类的整个生命周期分为以上七个阶段,验证、准备、解析统称为连接阶段。关于加载流程笔者之前也写过一篇文章JVM之类加载器,从代码层面了解类加载机制。下面我们将更加详细的讲解各个阶段,加载阶段只是类加载的一个步骤,类加载包括以上的七个步骤。 四、何时进行类加载 加虚拟机规范规定了如下几种情况就必须要进行初始化(开始类加载)。 1.  遇到new、getstatic、putstatic、invokestatic指令时,对应到程序中就是使用到new实例化对象时、读取或设置类静态字段时(非final)、调用静态方法时。需要进行初始化。 2. 使用java.lang.reflect包的方法对类进行反射调用时,需要进行初始化。 3. 使用一个类时,若其父类还未初始化,则需先初始化其父类。 4. 虚拟机启动时,包含main方法的类,虚拟机会将其初始化。 5. java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄,并且这个方法句柄对应的类没有进行初始化,则需要先进行初始化。 以上五种情况称为主动使用,其他的情况均称为被动使用,被动使用不会导致初始化。 五、初始化示例说明 1. 对于类而言,使用父类的静态字段(非final)不会导致子类的初始化。 class SuperClass { static { System.out.println("super"); } public…

Continue Reading 【JVM】JVM系列之类加载机制(四)

【JVM】JVM系列之Class文件(三)

一、前言 随着我们学习的不断深入,我相信读者对class文件很感兴趣,class文件是用户编写程序与虚拟机之前的桥梁,程序通过编译形成class文件,class文件之后会载入虚拟机,被虚拟机执行,下面我么来一起揭开class文件的神秘面纱。 二、什么是class文件 class文件是二进制文件,通常是以.class文件结尾的文件,它是以8位字节为基础单位的二进制流,各个数据项紧密排列在class文件中,数据项的基本类型为u1,u2,u4,u8,分别表示一个字节,两个字节,四个字节,八个字节的无符号数。 三、class文件数据结构 其实对于class文件而言,总体的数据结构看上去很规整,具体的结构如下图所示 下面我们将用一个例子详细讲解class文件的各个部分。 四、示例 public class Test implements Cloneable { private String name; public Test() { } public Test(String name) { this.name = name; } public…

Continue Reading 【JVM】JVM系列之Class文件(三)

【JVM】JVM系列之垃圾回收(二)

一、为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。 二、哪些内存需要进行垃圾回收 对于虚拟机中线程私有的区域,如程序计数器、虚拟机栈、本地方法栈都不需要进行垃圾回收,因为它们是自动进行的,随着线程的消亡而消亡,不需要我们去回收,比如栈的栈帧结构,当进入一个方法时,就会产生一个栈帧,栈帧大小也可以借助类信息确定,然后栈帧入栈,执行方法体,退出方法时,栈帧出栈,于是其所占据的内存空间也就被自动回收了。而对于虚拟机中线程共享的区域,则需要进行垃圾回收,如堆和方法区,线程都会在这两个区域产生自身的数据,占据一定的内存大小,并且这些数据又可能会存在相互关联的关系,所以,这部分的区域不像线程私有的区域那样可以简单自动的进行垃圾回收,此部分区域的垃圾回收非常复杂,而垃圾回收也主要是针对这部分区域。 三、垃圾收集算法 任何垃圾收集算法都必须做两件事情。首先,它必须检测出垃圾对象。其次,它必须回收垃圾对象所使用的堆空间并还给程序。那么问题来了,如何检测出一个对象是否为垃圾对象呢?一般有两种算法解决这个问题。1. 引用计数算法 2. 可达性分析算法。 1.引用计数算法 堆中的每一个对象有一个引用计数,当一个对象被创建,并把指向该对象的引用赋值给一个变量时,引用计数置为1,当再把这个引用赋值给其他变量时,引用计数加1,当一个对象的引用超过了生命周期或者被设置为新值时,对象的引用计数减1,任何引用计数为0的对象都可以被当成垃圾回收。当一个对象被回收时,它所引用的任何对象计数减1,这样,可能会导致其他对象也被当垃圾回收。 问题:很难检测出对象之间的额相互引用(引用循环问题) 如下代码段可以从反面验证虚拟机的垃圾回收不是采用的引用计数。 package com.leesf.chapter3; public class ReferenceCountingGC { public Object instance = null; private static final int _1MB =…

Continue Reading 【JVM】JVM系列之垃圾回收(二)