`

【zz】Java编码的理解和Java加载器的理解

 
阅读更多

一,我对java中编码的理解
1. 编码的产生  
  对电脑而言,只认识0,1; 而现实世界是由各种符合组成,要想让计算机解释现实世界,就必须建立一套现实世界中的符号 和 计算机能处理的符号之间的对应关系,这个对应关系就是编码  

2. 在一个编辑器中,当我们在键盘上敲入一个字符时,在该编辑器上就会显示对应的字符,这个过程用计算机执行步骤来解释大致如下:  
  输入字符 –> 编辑器根据设定的编码格式把字符编成01格式 -> 编辑器再按编码规则对01解码–> 显示字符  

3.几种常见的编码格式  
1. ASCII码:   
  计算机中最早的一套编码格式,采用7位二进制表示一个常见的字符,我们知道,计算机是按照字节来处理数据的,一个字节8位,因此用一个字节就可以表示一个ASCII字符,且还有一个位空位,规定最高位不用,常见的把最高位设定为0。 7位二进制最多可以表示128个字符(2的7次方),ASCII码只能表示常见的英文字符,数字,和少量的符号(没办法,谁让计算机是人家老美先发明的啊,优先考虑本土语言,理解理解)  
注: 由于ASCII最早定义,使用广泛,使得之后出现的新的”字符“(不是汉字喔)编码都尽量和它兼容  

2. iso-8859-1:  
  尽管ASCII应用广泛,但是由于它定义的字符太少,即使对于同是使用字母语言的国家也不够用,更别说我们汉字啦,西欧许多国家使用拉丁语言,其中的很多字符ASCII编码都不认识喔,这当然会让它们不爽啦,总不能因为这个问题让那些国家的人不使用电脑吧, 于是ISO/IEC就推出了另外的一套编码标准ISO-8859-1. 这套标准完全和ASCII兼容,它使用8位二进制表示一个字符 —--- 刚好一个字节,其中最高位是0时的解释和ASCII一样(这样不就完全兼容啦,兼容很好理解吧),但最高位是1时则用于定义其它字符,这样就在保证和ASCII兼容的同时又扩展了ASCII,可以多表示字符啦  

3. GBK编码  
  光有字母语言国家的编码就可以么?, 可以啊,好好学习英语啊, 要不你看不懂啊,不想学?,那就不玩啊,呵呵,当然不会啦,对于中国,韩国,日本等这些国家,推出了一种新的编码GBK码, 在编码上GBK采用单双字节混合的方式,它也兼容ASCII喔,具体GBK怎么个编码,你查看资料啦, 这里重点关注的是编码的演化,提供的是思路哈  

4. Unicode  
  Unicode是为了打破这种编码的各自为政,带有强烈地域性的标示而推出的一种编码格式,目的是要达到世界的大同,大同好啊,方便交流啊,就是晚了点,计算机一出现就出来多好,就没了现在让程序员头疼的编码转来转去的麻烦了,恩,看来有界限的人心是会带来麻烦的,好了,啰嗦了这么多,才算真正引入正题,为什么会出现乱码,如何解决乱码  
    
4. 揭示web中乱码的病因  
  比如说现在有两个人,张三 和 make分别来自中国和美国,现在他们访问同一台j2ee服务器,他们都向服务器发送了一条消息  
  张三: 嗨,我是张三  
  Make: hello, I’m make  
  假如张三发送的信息采用的编码格式是GBK, make的是ASCII, 对于浏览器而言,留言器没有把发送的信息采用的编码格式告诉给web服务器(之前的浏览器没提供这个功能,又是地域性的见识啊,现在最新版的不知道有没有),web服务器不知道你发过来的信息编码格式啊,怎么解释呢,没办法只好提供个默认的吧,恩还是用iso-8859-1吧(毕竟java也是老美搞出的啊,没办法),英语的没问题,web服务器能听懂,毕竟大家都说英语嘛,并且make对web服务器而言,懂得字母还少了点呢; 汉语的就不行了,就好比一个人只懂汉语,另一个人只懂英语,怎么交流啊,可以交流?那就只好”~!@#¥%“, 这就是java中乱码的病因吧  

5. 如何避免乱码的产生  
  知道了病因,对症下药就好啦,   
  1. 让浏览器明确指定信息的编码格式, 这个不行啦,程序员干涉不了啦,这不是你的问题啦,不知道现在的浏览器是否已提供这种机制啊,请知道的朋友明示:?  
  2. 明确采用GBK编码处理请求的数据啊  
  3. 因为一般的浏览器可以解析多种编码格式,我们的web响应内容,最好指定编码格式喔,这个大家都知道啦  
  4. 不知道那些国外的站点是如何处理中文的,请大师们开始啊  

二、我对java中类装载的理解 

1.Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,  
类装载器所做的工作实质是把类文件从硬盘读取到内存中  

2.java中的类大致分为三种:  
  1.系统类  
  2.扩展类  
  3.由程序员自定义的类  

3.类装载方式,有两种  
  1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中,  
  2.显式装载, 通过class.forname()等方法,显式加载需要的类  
  隐式加载与显式加载的区别:  
  两者本质是一样?,  
  ?  

4.类加载的动态性体现  
  一个应用程序总是由n多个类组成,Java程序启动时,并不是一次把所有的类全部加载后再  
运行,它总是先把保证程序运行的基础类一次性加载到jvm中,其它类等到jvm用到的时候再加载,这样的好处是节省了内存的开销,因为java最早就是为嵌入式系统而设计的,内存宝贵,这是一种可以理解的机制,而用到时再加载这也是java动态性的一种体现  

5.java类装载器  
  Java中的类装载器实质上也是类,功能是把类载入jvm中,值得注意的是jvm的类装载器并不是一个,而是三个,层次结构如下:  
  Bootstrap Loader - 负责加载系统类  
  |  
  - - ExtClassLoader - 负责加载扩展类  
  |  
  - - AppClassLoader - 负责加载应用类  
  为什么要有三个类加载器,一方面是分工,各自负责各自的区块,另一方面为了实现委托模型,下面会谈到该模型
 
6. 类加载器之间是如何协调工作的  
  前面说了,java中有三个类加载器,问题就来了,碰到一个类需要加载时,它们之间是如何协调工作的,即java是如何区分一个类该由哪个类加载器来完成呢。  
在这里java采用了委托模型机制,这个机制简单来讲,就是“类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入,如果Parent 找不到,那么才由自己依照自己的搜索路径搜索类”,注意喔,这句话具有递归性  
下面举一个例子来说明,为了更好的理解,先弄清楚几行代码:  
Public class Test{  
  Public static void main(String[] arg){  
  ClassLoader c = Test.class.getClassLoader(); //获取Test类的类加载器  
  System.out.println(c);   
  ClassLoader c1 = c.getParent(); //获取c这个类加载器的父类加载器  
  System.out.println(c1);  
  ClassLoader c2 = c1.getParent();//获取c1这个类加载器的父类加载器  
  System.out.println(c2);  
  }  
 
把以上代码存到d:\my 文件夹下,直接编译,然后在dos模式下运行  
D:\my\java Test  
  。。。AppClassLoader。。。  
  。。。ExtClassLoader。。。  
  Null  

D:\my  

注: 。。。表示省略了内容  
可以看出Test是由AppClassLoader加载器加载的  
AppClassLoader的Parent 加载器是 ExtClassLoader  

但是ExtClassLoader的Parent为 null 是怎么回事呵,朋友们留意的话,前面有提到Bootstrap Loader是用C++语言写的,依java的观点来看,逻辑上并不存在Bootstrap Loader的类实体,所以在java程序代码里试图打印出其内容时,我们就会看到输出为null  
【注:以下内容大部分引用java深度历险】  
弄明白了上面的示例,接下来直接进入类装载的委托模型实例,写两个文件,如下:  
文件:Test1.java  
Public class Test1{  
  Public static void main(String[] arg){  
  System.out.println(Test1.class.getClassLoader());  
  Test2 t2 = new Test2();  
  T2.print();  
  }  
 

文件: Test2.java  
Public class Test2{  
  Public void prin(){  
  System.out.println(this.getClass().getClassLoader());  
  }  
 

这两个类的作用就是打印出载入它们的类装载器是谁, 将这两个文件保存到d:\my目录下,编译后,我们在复制两份,分别置于 <JRE所在目录>\classes下(注意,刚开始我们的系统下没有此目录,需自己建立) 与 <JRE所在目录>\lib\ext\classes下(同样注意,开始我们的系统下也没此目录,手工建立), 然后切换到d:\my目录下开始测试,  

测试一:  
<JRE所在目录>\classes下  
Test1.class  
Test2.class  

<JRE所在目录>\lib\ext\classes下  
Test1.class  
Test2.class  

D:\my下  
Test1.class  
Test2.class  


dos下输入运行命令,结果如下:  
D:\my>java Test1  
Null  
Null  

D:\my>  
    
  从输出结果我们可以看出,当AppClassLoader要载入Test1.class时,先请其Parent,也就是ExtClassLoader来载入,而ExtclassLoader又请求其Parent,即Bootstrap Loader来载入Test1.class. 由于 <JRE所在目录>\Classes目录为Bootstrap Loader的搜索路径之一,所以Bootstrap Loader找到了Test1.class,因此将它载入,接着在Test1.class之内有载入Test2.class的需求,由于Test1.class是由Bootstrap Loader所载入,所以Test2.class内定是由Bootstrap Loader根据其搜索路径来找,因Test2.class也位于Bootstrap Loader可以找到的路径下,所以也被载入了,最后我们看到Test1.class与Test2.class都是由Bootstrap Loader(null)载入。  


测试二:  
<JRE所在目录>\classes下  
Test1.class  

<JRE所在目录>\lib\ext\classes下  
Test1.class  
Test2.class  

D:\my下  
Test1.class  
Test2.class  

dos下输入运行命令,结果如下:  
D:\my>java Test1  
Null  
Exception in thread “main” java.lang.NoClassdefFoundError:Test2 at Test1.main。。。  
D:\my>  

  从输出结果我们可以看出,当AppClassLoader要载入Test1.class时,先请其Parent,也就是ExtClassLoader来载入,而ExtclassLoader又请求其Parent,即Bootstrap Loader来载入Test1.class. 由于 <JRE所在目录>\Classes目录为Bootstrap Loader的搜索路径之一,所以Bootstrap Loader找到了Test1.class,因此将它载入,接着在Test1.class之内有载入Test2.class的需求,由于Test1.class是由Bootstrap Loader所载入,所以Test2.class内定是由Bootstrap Loader根据其搜索路径来找,但是因为Bootstrap Loader根本找不到Test2.class(被我们删除了),而Bootstrap Loader又没有Parent,所以无法载入Test2.class.最后我们看到Test1.class是由Bootstrap Loader(null)载入,而Test2.class则无法载入  


测试三  
<JRE所在目录>\classes下  

Test2.class  

<JRE所在目录>\lib\ext\classes下  
Test1.class  
Test2.class  

D:\my下  
Test1.class  
Test2.class  

dos下输入运行命令,结果如下:  
D:\my>java Test1  
。。。ExtClassLoader。。。  
Null  

D:\my>  

  从输出结果我们可以看出,当AppClassLoader要载入Test1.class时,先请其Parent,也就是ExtClassLoader来载入,而ExtclassLoader又请求其Parent,即Bootstrap Loader来载入Test1.class.但是Bootstrap Loader无法在其搜索路径下找到Test1.class(被我们删掉了),所以ExtClassLoader只得自己搜索,因此ExtClassLoader在其搜索路径 <JRE所在目录>\lib\ext\classes下找到了Test1.class,因此将它载入,接着在Test1.class之内有载入Test2.class的需求,由于Test1.class是由ExtClassLoader所载入,所以Test2.class内定是由ExtClassLoader根据其搜索路径来找,但是因为ExtClassLoader有Parent,所以先由Bootstrap Loader帮忙寻找,Test2.class位于Bootstrap Loader可以找到的路径下,所以被Bootstrap Loader载入了.最后我们看到Test1.class是由ExtClassLoader载入,而Test2.class则是由Bootstrap Loader(null)载入  

  了解了以上规则,请朋友们自行分析以下场景的执行结果  

测试四:  
<JRE所在目录>\classes下  


<JRE所在目录>\lib\ext\classes下  
Test1.class  
Test2.class  

D:\my下  
Test1.class  
Test2.class  


测试五:  
<JRE所在目录>\classes下  


<JRE所在目录>\lib\ext\classes下  
Test1.class  


D:\my下  
Test1.class  
Test2.class  


测试六:  
<JRE所在目录>\classes下  


<JRE所在目录>\lib\ext\classes下  

Test2.class  


D:\my下  
Test1.class  
Test2.class  


测试七:  
<JRE所在目录>\classes下  


<JRE所在目录>\lib\ext\classes下  


D:\my下  
Test1.class  
Test2.class  

分享到:
评论

相关推荐

    阿里巴巴java笔试zz.

    9. 小猴子的荔枝问题:此题是关于心理预期和营销策略的,与编程直接关联不大,但在软件开发中,理解用户需求和预期同样关键。 10. 英语题目未给出,无法解析。 以上问题主要涉及逻辑推理、决策分析、问题解决等软...

    zz.rar_JAVA俄罗斯方块

    本项目“zz.rar_JAVA俄罗斯方块”提供了一套完整的JAVA源代码,让开发者可以深入理解如何用JAVA语言实现这个经典游戏。本文将详细解析该项目中的关键知识点,帮助读者更好地理解和掌握JAVA编程技巧。 1. **JAVA基础...

    基于Java与HTML的studyjava-zz设计源码,深入探索Java编程新视野

    该项目为“studyjava-zz”设计源码,深入探索Java编程新视野,共计包含549个文件,涵盖209个Java源代码文件、74个Git忽略文件、70个项目配置文件、68个classpath文件、66个偏好设置文件、25个Markdown文档、16个XML...

    Zz: java 线程池设计思想

    Java线程池是一种高效管理线程资源的工具,它的设计思想是基于生产者消费者模型,借鉴了工厂模式和代理模式的元素。线程池通过维护一组可重用线程,减少了创建和销毁线程的开销,提高了系统响应速度与并发处理能力。...

    base zz zz zz zz

    base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz

    聊天工具的java开发 超越QQ 天翔ZZ

    本文将深入探讨使用Java语言开发聊天工具的关键知识点,结合"天翔ZZ"这个项目,我们将分析服务器程序和客户端程序的设计与实现。 首先,Java作为跨平台的编程语言,因其强大的网络编程能力而成为开发聊天工具的理想...

    (zz)java集合类总结

    ### Java集合类总结 在Java开发中,集合类(Containers)是极其重要的组成部分,它们作为...通过以上对Java集合框架的全面解析,我们可以更好地理解和运用这些强大的工具,在实际开发中构建更加高效、健壮的应用程序。

    java中四个核心思想

    ### Java中的四个核心思想 Java作为一种广泛使用的编程语言,在其设计与实现中蕴含了四大核心思想,这四...通过理解这四个核心思想,我们可以更好地掌握Java语言的特点和优势,同时也能更加高效地进行Java程序的开发。

    java实现logistic回归算法

    - **模型保存与加载**:使用序列化技术如Java的Serializable接口保存和加载模型。 4. **Java库的使用** - **Apache Commons Math**:提供了一些数学工具,如矩阵运算、优化算法等,适合实现Logistic回归。 - **...

    java 银行管理系统

    以上是“Java银行管理系统”的主要知识点,通过该项目的学习和实践,学生可以全面了解一个实际软件开发的流程,包括需求分析、设计、编码、测试和维护等阶段,同时加深对Java编程和数据库管理的理解。

    Java图形界面学生签到考勤系统MySQL数据库.zip

    Java图形界面学生签到考勤系统是一个利用MySQL数据库进行数据存储的软件应用,它专为在校学生设计,旨在简化考勤流程,...通过学习和实践这样的项目,开发者可以提升自己的综合技能,并对实际应用场景有更深入的理解。

    解决java.security.InvalidKeyException: Illegal key size

    在Java编程环境中,有时会遇到一个常见的错误:"java.security.InvalidKeyException: Illegal key size"。...这个过程涉及到对Java安全策略的理解,以及对系统环境变量的熟悉,对于开发和运维人员来说是必要的知识。

    字符集编码的识别(zz)

    字符集编码是将字符与二进制数字之间建立映射关系的一种方法,使得计算机能够理解和处理各种语言的文字。常见的字符集编码有ASCII、GBK、UTF-8等。 这篇由博主Leo在CSDN.NET上发表的文章可能详细阐述了如何识别和...

    高分springboot毕设+vue的招聘求职系统_zz-Java源码.zip

    本项目的开发不仅是为了满足计算机相关专业学生的毕设需求,更是为了提供一个实战练习的平台,帮助Java学习者提升实际开发能力,理解企业级应用的开发流程和技术要点。通过参与这一项目,学生们可以更好地掌握Spring...

    Aspose.cad19.5+dwg使用Java转pdf

    在IT行业中,转换文件格式是一项常见的任务,尤其是在处理CAD(计算机辅助设计)文件时。Aspose是一个强大的文件处理库,提供了...结合适当的项目管理工具和良好的编程实践,可以高效地集成这个功能到任何Java应用中。

    JAVA源码Java火影忍者游戏源代码

    总之,利用Java开发“火影忍者”游戏不仅可以让开发者深入了解Java语言本身的特点,还能够学习到游戏开发中涉及的各种技术和方法。通过不断实践和学习,开发者将能够在这一领域取得更大的进步。

    10种java性能优化方案.docx

    通过对文档中提到的关键点进行深入探讨,我们可以更好地理解如何有效地优化Java程序。无论是从代码层面还是从架构层面出发,这些策略都是为了提高系统的整体性能,从而满足不断增长的需求和挑战。

    JAVA源码Java编写的网页版魔方游戏

    根据提供的文件信息,我们可以深入探讨以下几个关键的知识点: ### 一、Java在Web游戏开发中的应用 #### 1. Java Web技术栈 ...希望这些知识点能够帮助您更好地理解Java在Web游戏开发领域的应用。

    java面试题目20页可已打印题目含解析和答案

    Java面试题目常常涵盖了许多核心概念和技术,这些都是...理解这些基本概念对于Java开发者来说至关重要,特别是在面试中,它们经常被用来测试候选人的基础和实践经验。熟悉并能熟练运用这些知识点将有助于提升面试表现。

    JAVA基于Swing和MySql的考试系统

    【JAVA基于Swing和MySql的考试系统】是一款学生大作业项目,它集成了Java的Swing图形用户界面库和MySQL关系型数据库管理系统,用于创建一个功能完善的在线考试平台。这个系统具有设置起止时间、自动批改试卷以及进行...

Global site tag (gtag.js) - Google Analytics