文档章节

JAVA基础之类加载器

克温s
 克温s
发布于 2015/12/01 20:48
字数 1328
阅读 5
收藏 0
  1. 编译器:为JVM转换源指令,将.java文件转换为.class的字节码文件;

  2. 解释器:将字节码文件翻译成目标机器的机器语言;

  3. JVM仅加载程序执行时所需要的类文件,假设程序从MyProgram.class开始运行,其过程如下:

    1. 类加载:从磁盘上读取文件或请求Web上的文件,加载MyProgram.class中的内容;

    2. 类分析:如果MyProgram.class中存在类型为另一个类的域,或者是拥有超类,那么这些类文件也会被加载;

    3. 接着,JVM执行MyProgram中的main方法(它是静态的,无需创建类的实例);

    4. 如果main方法或者main调用的方法要用到更多的类,那么接下来会加载这些类。

  4. 类加载器分类:

    1. 引导类加载器:加载系统类,通常从rt.jar开始,通常是用C语言来实现;

    2. 扩展类加载器:加载jre/lib/ext中的标准扩展类,不产生类路径

    3. 系统类加载器(应用类加载器):加载应用类,CLASSPATH配置的类文件,产生类路径

  5. 类加载器的层次结构:

    类加载器有一种父/子关系,除了引导类加载器外,每个类加载都有一个父类加载器;加载类的时候,父类有一次加载机会,只有父类加载失败才加载指定的类:

    URL url = new URL("file:///*.jar");

    URLClassLoader pluginLoader = new URLClassLoader(new URL[]{url});

     Class<?> cl = pluginLoader.loadClass("myPackage.MyClass");

    因为在URLClassLoader构造中没有指定父类加载器,因此插件类的父类就是系统类加载器(应用类)。

  6. 类加载器倒置:

    Class.forName()使用的是系统类加载器(应用类),如果有一个插件类希望被类加载器加载,系统类加载器对插件类是不可见的,所以就需要使用插件类加载器。

  7. 每个线程都有一个对类加载器的引用,称为上下文类加载器。主线程的上下文类加载器是系统类加载器,所以,如果不作任何操用,所有的线程都会是系统类加载器。

  8.         URL url = new URL("file:///*.jar");
            URLClassLoader pluginLoader = new URLClassLoader(new URL[]{url});
            //设置上下文类加载器为指定的类加载器
            Thread t = Thread.currentThread();
            t.setContextClassLoader(pluginLoader);
            //调用类
            Class<?> cl = pluginLoader.loadClass("myPackage.MyClass")
  9. 在同一个JVM中,可以有两个类,它们的包名和类名都相同,这是因为类是由它人全名和类加载器来确定的。

  10. 类加载器应用场景:加密软件,将类文件存储到数据库等

  11. 定制类加载器

  12. import java.io.FileInputStream;
    import java.io.FileOutputStream;
    
    public class Caesar {
    
        public static void main(String[] args) {
            if (args.length != 3) {
                System.out.println("USAGE: java classloader.Caesar in out key");
                return;
            }
    
            try {
                FileInputStream in = new FileInputStream(args[0]);
                FileOutputStream out = new FileOutputStream(args[1]);
                int key = Integer.parseInt(args[2]);
                int ch = 0;
                while ((ch = in.read()) != -1) {
                    byte c = (byte) (ch + key);
                    out.write(c);
                }
            } catch (Exception e) {
            }
        }
    
    }
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class CryptoClassLoader extends ClassLoader {
        private int key;
    
        public CryptoClassLoader(int key) {
            this.key = key;
        }
    
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {
                byte[] classBytes = null;
                classBytes = loadClassBytes(name);
                //调用超类ClassLoader的defineClass方法,向JVM提供字节码
                Class<?> cl = defineClass(name, classBytes, 0, classBytes.length);
                if (cl == null)
                    throw new ClassNotFoundException(name);
                return cl;
            } catch (Exception e) {
                throw new ClassNotFoundException(name);
            }
        }
    
        private byte[] loadClassBytes(String name) throws IOException {
            String cname = name.replace('.', '/') + ".caesar";
            InputStream in = new FileInputStream(new File(cname));
            byte[] bytes = toByteArray(in);
            for (int i = 0; i < bytes.length; i++)
                bytes[i] = (byte) (bytes[i] - key);
            in.close();
            return bytes;
        }
    
        //字符流转字节流
        private byte[] toByteArray(InputStream in) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int offset = 0;
            while ((offset = in.read(buffer)) != -1) {
                out.write(buffer, 0, offset);
            }
            out.close();
            return out.toByteArray();
        }
    
    }
    import java.awt.GridBagConstraints;
    
    public class GBC extends GridBagConstraints {
        public GBC(int gridx, int gridy) {
            this.gridx = gridx;
            this.gridy = gridy;
        }
    
        public GBC(int gridx, int gridy, int gridwidth, int gridheight) {
            this.gridx = gridx;
            this.gridy = gridy;
            this.gridwidth = gridwidth;
            this.gridheight = gridheight;
        }
    
        public GBC setSpan(int gridwidth, int gridheight) {
            this.gridwidth = gridwidth;
            this.gridheight = gridheight;
            return this;
        }
    
        public GBC setAnchor(int anchor) {
            this.anchor = anchor;
            return this;
        }
    
        public GBC setFill(int fill) {
            this.fill = fill;
            return this;
        }
    
        public GBC setWeight(double weightx, double weighty) {
            this.weightx = weightx;
            this.weighty = weighty;
            return this;
        }
    
        public GBC setInsets(int distance) {
            this.insets = new java.awt.Insets(distance, distance, distance, distance);
            return this;
        }
    
        public GBC setInsets(int top, int left, int bottom, int right) {
            this.insets = new java.awt.Insets(top, left, bottom, right);
            return this;
        }
    
        public GBC setIpad(int ipadx, int ipady) {
            this.ipadx = ipadx;
            this.ipady = ipady;
            return this;
        }
    
    }
    import java.awt.GraphicsConfiguration;
    import java.awt.GridBagLayout;
    import java.awt.HeadlessException;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.lang.reflect.Method;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JTextField;
    
    public class ClassLoaderFrame extends JFrame {
        private JTextField       keyField        = new JTextField("3", 4);
        private JTextField       nameField       = new JTextField("Calculator", 30);
        private static final int DEFAULT_WIDTH   = 300;
        private static final int DEFAULT_HIENGTH = 200;
    
        public ClassLoaderFrame() throws HeadlessException {
            setSize(DEFAULT_WIDTH, DEFAULT_HIENGTH);
            setLayout(new GridBagLayout());
            add(new JLabel("Class"), new GBC(0, 0).setAnchor(GBC.EAST));
            add(nameField, new GBC(1, 0).setWeight(100, 0).setAnchor(GBC.WEST));
            add(new JLabel("Key"), new GBC(0, 1).setAnchor(GBC.EAST));
            add(keyField, new GBC(1, 1).setWeight(100, 0).setAnchor(GBC.WEST));
            JButton loadButton = new JButton("Load");
            add(loadButton, new GBC(0, 2, 2, 1));
            loadButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent event) {
                    runClass(nameField.getText(), keyField.getText());
                }
            });
        }
    
        public void runClass(String name, String key) {
            try {
                //调用classloader,传递解密key
                ClassLoader loader = new CryptoClassLoader(Integer.parseInt(key));
                Class<?> c = loader.loadClass(name);
                Method m = c.getMethod("main", String[].class);
                m.invoke(null, (Object) new String[] {});
            } catch (Throwable e) {
                JOptionPane.showMessageDialog(this, e);
            }
        }
    
        public ClassLoaderFrame(GraphicsConfiguration gc) {
            super(gc);
        }
    
        public ClassLoaderFrame(String title) throws HeadlessException {
            super(title);
        }
    
        public ClassLoaderFrame(String title, GraphicsConfiguration gc) {
            super(title, gc);
        }
    
    }
    import java.awt.EventQueue;
    
    import javax.swing.JFrame;
    
    public class ClassLoaderTest {
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new ClassLoaderFrame();
                    frame.setTitle("ClassLoaderTest");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setVisible(true);
                }
            });
        }
    }
  13. 字节码校验

    当类加载器将新加载的Java平台类的字节码传递给JVM时,这些字节码首先要接受“校验器”的校验,除了系统类外,所有的类都要校验。

  14. 安全管理器

    字节码通过校验后,第二种安全机制就会启动,安全管理器是一个负责控制具体操作是否允许执行类。


© 著作权归作者所有

克温s
粉丝 2
博文 52
码字总数 19221
作品 0
东城
项目经理
私信 提问
为什么Java中有三种基础的类加载器?

引言 Java中有三种基础的类加载器 BootStrap, Extension and System 他们都有一个职能,就是从不同的包中加载类。 但是一个类加载器完全可以加载所有的类,为什么要有3种基础的类型的类加载器...

Java猫
01/12
0
0
(转)一张图看懂JVM之类装载系统

导读 在之前的文章中,我们通过一张图的方式(图:pointup2:)整体上了解了JVM的结构,并重点讲解了JVM的内存结构、内存回收算法及回收器方面的知识。收到了不少读者朋友们的反馈和指正,在这...

西瓜1994
2018/12/04
58
1
深入浅出 ClassLoader

内容概述 “类加载”介绍 “类加载器”介绍 深入“类加载器” 深入“父亲委托机制” 一,“类加载”介绍 “加载”是类加载的时机的第一阶段。 类从被加载到虚拟机内存中开始,到卸载出内存为...

tomas家的小拨浪鼓
08/04
0
0
面试中关于Java虚拟机(jvm)的问题看这篇就够了

最近看书的过程中整理了一些面试题,面试题以及答案都在我的文章中有所提到,希望你能在以问题为导向的过程中掌握虚拟机的核心知识。面试毕竟是面试,核心知识我们还是要掌握的,加油~~~ 下面...

snailclimb
2018/05/12
0
0
Java Classloader机制解析

做Java开发,对于ClassLoader的机制是必须要熟悉的基础知识,本文针对Java ClassLoader的机制做一个简要的总结。因为不同的JVM的实现不同,本文所描述的内容均只限于Hotspot Jvm. 本文将会从...

aminqiao
2014/05/09
24K
2

没有更多内容

加载失败,请刷新页面

加载更多

Tensorflow 2.0安装

Tensorflow2.0安装环境: Ubuntu 16.04或更高(64位) Windows 7或者更高(64位,且支持python3) 安装Tensorflow 2.0 GPU版本的需要安装NVIDIA相关软件包: NVIDIA驱动 :版本必须410.x或更...

JosiahMg
19分钟前
4
0
TL138/1808/6748F-EasyEVM开发板硬件、CPU、FLASH、RAM

TL138/1808/6748F-EasyEVM是广州创龙基于SOM-TL138/SOM-TL1808/SOM-TL6748F核心板开发的一款开发板。由于SOM-TL138/SOM-TL1808/SOM-TL6748核心板管脚兼容,所以此三个核心板共用同一个底板。...

Tronlong创龙
27分钟前
4
0
百度嵌入式AI解决方案EdgeBoard之内存驱动设计介绍

1. 背景介绍 由于 FPGA 具备可编程和高性能计算的特点,基于FPGA硬件的AI计算加速,正广泛地应用到计算机视觉处理领域。其中极具代表性的部署方式之一就是使用FPGA和CPU组合构成异构计算系统...

AI君
33分钟前
6
0
开放应用模型(OAM):全球首个云原生应用标准定义与架构模型

Kubernetes 项目作为容器编排领域的事实标准, 成功推动了诸如阿里云 Kubernetes (ACK)等云原生服务的迅速增长。但同时我们也关注到,Kubernetes 的核心 API 资源比如 Service、Deploymen...

Mr_zebra
36分钟前
4
0
《Linux操作系统-Exynos4412》编译和安装Busybox

开发环境:Exynos4412-iTOP-4412开发板 现在 Busybox 的配置已经完成了,接下来开始编译 Busybox,在 Ubuntu 的终端输入 “make”命令开始编译 Busybox,如下图。 下图为编译过程中的截图。 ...

书白
39分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部