搜索
首页数据库mysql教程初探Java类加载机制_MySQL

初探Java类加载机制_MySQL

Jun 01, 2016 pm 02:06 PM
classloaderstring文件方法机制

  一、在jdk1.2以后,类加载是通过委托来完成的,这意味着如果 ClassLoader 不能找到类,它会请求父代 ClassLoader 来执行此项任务,所有 ClassLoaders 的根是系统 ClassLoader,它会以缺省方式装入类 -- 即,从本地文件系统。今天我们就来探讨一下在jvm中这些机制是怎样运行的。让我们假设有一个class字节码文件(比如Hello.class文件),那么在应用程序中,他是如何被加载进来,并形成一个类对象的呢?我们这篇文章的目的就是为了解释这个问题。

  在java.lang包里有个ClassLoader类,ClassLoader 的基本目标是对类的请求提供服务。当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 试图返回一个表示这个类的 Class 对象。通过覆盖对应于这个过程不同阶段的方法,可以创建定制的 ClassLoader。其中有个loadClass(String name, boolean resolve)方法,该方法为ClassLoader的入口点,在jdk1.2以后,loadClass方法将缺省调用findClass方法,详细内容可以参考API文档,我们编写的ClassLoader主要就是为了覆盖以上两个方法。回到我们刚才的问题,怎样读进字节码文件,并把它构成一个类对象呢?在ClassLoader里有个方法,Class defineClass(String name, byte[] b, int off, int len),答案就在这里了,我们根据把class字节码文件(如Hello.class)读进一个字节数组里,byte[] b,并把它转化为Class对象,而这些数据可以来源于文件,网络等,神奇吧:)

  defineClass管理 JVM 的许多复杂、神秘和倚赖于实现的方面 -- 它把字节码分析成运行时数据结构、校验有效性等等。不必担心,您无需亲自编写它。事实上,即使您想要这么做也不能覆盖它,因为它已被标记成最终的。

  其他一些方法:

  findSystemClass方法:从本地文件系统装入文件。它在本地文件系统中寻找类文件,如果存在,就使用 defineClass 将原始字节转换成 Class 对象,以将该文件转换成类。

  findClass方法:jdk1.2以后loadClass 的缺省实现调用这个新方法。findClass 的用途包含您的 ClassLoader 的所有特殊代码,而无需要复制其它代码(例如,当专门的方法失败时,调用系统 ClassLoader)。

  getSystemClassLoader: 如果覆盖 findClass 或 loadClass,getSystemClassLoader 使您能以实际 ClassLoader 对象来访问系统 ClassLoader(而不是固定的从 findSystemClass 调用它)。

  getParent:为了将类请求委托给父代 ClassLoader,这个新方法允许 ClassLoader 获取它的父代 ClassLoader。当使用特殊方法,定制的 ClassLoader 不能找到类时,可以使用这种方法。

  resolveClass: 可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的 loadClass 时,可以调用 resolveClass,这取决于 loadClass 的 resolve 参数的值。
  findLoadedClass:充当一个缓存,当请求 loadClass 装入类时,它调用该方法来查看 ClassLoader 是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。应首先调用该方法。

  二、工作流程:

  1)调用 findLoadedClass(String) 来查看是否存在已装入的类,如果没有,那么采用那种特殊的神奇方式来获取原始字节。

  2)通过父类ClassLoader调用loadClass方法,如果父类ClassLoader是null,那么按缺省方式装入类,即系统ClassLoader。

  3)调用findClass(String)去查找类并获取类;

  4)如果loadClass 的 resolve 参数的值为true,那么调用 resolveClass 解析 Class 对象.

  5)如果还没有类,返回 ClassNotFoundException。

  6)否则,将类返回给调用程序。

  三、一个实现了ClassLoader的例子:

  /**
  *CompilingClassLoader.java
  *Copyright 2005-2-12
  */
  import java.io.*;

  public class CompilingClassLoader extends ClassLoader{
  //读取一个文件的内容
  private byte[] getBytes(String filename) throws IOException{
  File file=new File(filename);
  long len=file.length();
  byte[] raw=new byte[(int)len];

  FileInputStream fin=new FileInputStream(file);

  int r=fin.read(raw);
  if(r!=len) throw new IOException("Can't read all,"+r+"!="+len);

  fin.close();

  return raw;
  }

  private boolean compile(String javaFile) throws IOException{
  System.out.println("CCL:Compiling "+javaFile+"...");
  //调用系统的javac命令
  Process p=Runtime.getRuntime().exec("javac "+javaFile);
  try{
  //其他线程都等待这个线程完成
  p.waitFor();
  }catch(InterruptedException ie){
  System.out.println(ie);
  }
  int ret=p.exitValue();

  return ret==0;
  }

  public Class loadClass(String name,boolean resovle) throws ClassNotFoundException{
  Class clas=null;

  clas=findLoadedClass(name);

  //这里说明了包的表示
  String fileStub=name.replace('.','/');

  String javaFilename=fileStub+".java";
  String classFilename=fileStub+".class";

  File javaFile=new File(javaFilename);
  File classFile=new File(classFilename);

  //如果存在class文件就不编译
  if(javaFile.exists()&&(!classFile.exists()||javaFile.lastModified()>classFile.lastModified())){
  try{
   if(!compile(javaFilename)||!classFile.exists()){
    throw new ClassNotFoundException("ClassNotFoundExcetpion:"+javaFilename);
   }
  }catch(IOException ie){
   throw new ClassNotFoundException(ie.toString());
  }
  }

  try{
  byte[] raw=getBytes(classFilename);

  //通过读入数据来构造一个类结构,这是核心
  clas=defineClass(name,raw,0,raw.length);
  }catch(IOException ie){
  //
  }

  if(clas==null){
  clas=findSystemClass(name);
  }

  System.out.println("findSystemClass:"+clas);

  if(resovle && clas!=null){
  resolveClass(clas);
  }

  if(clas==null){
  throw new ClassNotFoundException(name);
  }

  return clas;
  }
  }
  测试该loader:
  /**
  *TestRun.java
  *Copyright 2005-2-11
  */
  import java.lang.reflect.*;

  public class TestRun{
  public static void main(String[] args) throws Exception{
  String progClass=args[0];

  String progArgs[]=new String[args.length-1];
  System.arraycopy(args,1,progArgs,0,progArgs.length);

  CompilingClassLoader ccl=new CompilingClassLoader();

  Class clas=ccl.loadClass(progClass);

  //返回一个class的type
  Class[] mainArgType={(new String[0]).getClass()};
  Method main=clas.getMethod("main",mainArgType);

  Object argsArray[]={progArgs};

  main.invoke(null,argsArray);

  }
  }

  以上的核心内容已经编写完了,编译后,我们得到两个文件:

  CompilingClassLoader.class,TestRun.class

  四、编写一个例子,然后运行我们的ClassLoader

  /**
  *Hello.java
  */
  public class Hello{
  public static void main(String[] args){
  if(args.length!=1){
   System.err.println("Error,exit!");
   System.exit(1);
  }
  String name=args[0];
  System.out.println("Hello,"+name);
  }
  }

  好了,运行java TestRun Hello 阿飞

  ....
  ....
  ....
  Hello,阿飞

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
MySQL中的存储过程是什么?MySQL中的存储过程是什么?May 01, 2025 am 12:27 AM

存储过程是MySQL中的预编译SQL语句集合,用于提高性能和简化复杂操作。1.提高性能:首次编译后,后续调用无需重新编译。2.提高安全性:通过权限控制限制数据表访问。3.简化复杂操作:将多条SQL语句组合,简化应用层逻辑。

查询缓存如何在MySQL中工作?查询缓存如何在MySQL中工作?May 01, 2025 am 12:26 AM

MySQL查询缓存的工作原理是通过存储SELECT查询的结果,当相同查询再次执行时,直接返回缓存结果。1)查询缓存提高数据库读取性能,通过哈希值查找缓存结果。2)配置简单,在MySQL配置文件中设置query_cache_type和query_cache_size。3)使用SQL_NO_CACHE关键字可以禁用特定查询的缓存。4)在高频更新环境中,查询缓存可能导致性能瓶颈,需通过监控和调整参数优化使用。

与其他关系数据库相比,使用MySQL的优点是什么?与其他关系数据库相比,使用MySQL的优点是什么?May 01, 2025 am 12:18 AM

MySQL被广泛应用于各种项目中的原因包括:1.高性能与可扩展性,支持多种存储引擎;2.易于使用和维护,配置简单且工具丰富;3.丰富的生态系统,吸引大量社区和第三方工具支持;4.跨平台支持,适用于多种操作系统。

您如何处理MySQL中的数据库升级?您如何处理MySQL中的数据库升级?Apr 30, 2025 am 12:28 AM

MySQL数据库升级的步骤包括:1.备份数据库,2.停止当前MySQL服务,3.安装新版本MySQL,4.启动新版本MySQL服务,5.恢复数据库。升级过程需注意兼容性问题,并可使用高级工具如PerconaToolkit进行测试和优化。

您可以使用MySQL的不同备份策略是什么?您可以使用MySQL的不同备份策略是什么?Apr 30, 2025 am 12:28 AM

MySQL备份策略包括逻辑备份、物理备份、增量备份、基于复制的备份和云备份。1.逻辑备份使用mysqldump导出数据库结构和数据,适合小型数据库和版本迁移。2.物理备份通过复制数据文件,速度快且全面,但需数据库一致性。3.增量备份利用二进制日志记录变化,适用于大型数据库。4.基于复制的备份通过从服务器备份,减少对生产系统的影响。5.云备份如AmazonRDS提供自动化解决方案,但成本和控制需考虑。选择策略时应考虑数据库大小、停机容忍度、恢复时间和恢复点目标。

什么是mySQL聚类?什么是mySQL聚类?Apr 30, 2025 am 12:28 AM

MySQLclusteringenhancesdatabaserobustnessandscalabilitybydistributingdataacrossmultiplenodes.ItusestheNDBenginefordatareplicationandfaulttolerance,ensuringhighavailability.Setupinvolvesconfiguringmanagement,data,andSQLnodes,withcarefulmonitoringandpe

如何优化数据库架构设计以在MySQL中的性能?如何优化数据库架构设计以在MySQL中的性能?Apr 30, 2025 am 12:27 AM

在MySQL中优化数据库模式设计可通过以下步骤提升性能:1.索引优化:在常用查询列上创建索引,平衡查询和插入更新的开销。2.表结构优化:通过规范化或反规范化减少数据冗余,提高访问效率。3.数据类型选择:使用合适的数据类型,如INT替代VARCHAR,减少存储空间。4.分区和分表:对于大数据量,使用分区和分表分散数据,提升查询和维护效率。

您如何优化MySQL性能?您如何优化MySQL性能?Apr 30, 2025 am 12:26 AM

tooptimizemysqlperformance,lofterTheSeSteps:1)inasemproperIndexingTospeedUpqueries,2)使用ExplaintplaintoAnalyzeandoptimizequeryPerformance,3)ActiveServerConfigurationStersLikeTlikeTlikeTlikeIkeLikeIkeIkeLikeIkeLikeIkeLikeIkeLikeNodb_buffer_pool_sizizeandmax_connections,4)

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具