Inside Class Loaders

原文:http://onjava.com/pub/a/onjava/2003/11/12/classloader.html

    In this part, I want to lay the groundwork on which we can start a discussion about dynamic and modular software systems. Class loaders may seem to be a dry topic, but I think it is one of the topics that separate the junior from the senior software engineer, so bear with me for an exciting journey into the darker corners of Java. 

    Now you may ask yourself, "Why should I deal with multiple class loaders and their limitations and problems?" The short answer is that you probably have to, one way or the other. Even when you write a simple servlet or JSP program and deploy within a servlet container, your code is loaded by your very own class loader, preventing you from accessing other web applications' classes. In addition, many "container-type" applications such as J2EE servers, web containers, NetBeans, and others are using custom class loaders in order to limit the impact of classes provided by a component, and thus will have an impact on the developer of such components.

    As we will see later, even with dynamic class loading, there can only be one class loaded in a particular JVM. Additional class loaders enable a developer to partition the JVM so that the reduced visibility of a class makes it possible to have multiple, different definitions of the same class loaded.

    The class loaders work like the federal bank of each country, issuing their own currency. The border of each country defines the visibility and usability of the currency and makes it possible to have multiple currencies in the world.

    First we need to explain some definitions.

CL:  Class loader. 
Initial CL:  The CL that initiated the loading of the class. 
Effective CL:  The CL that actually loaded the class. 
Class type:  The fully qualified class name (package plus class name). 
Class:  A combination of the class type and effective class loader.  
java.lang.Class:  A class in the JDK that represents a class (name, fields, methods, etc.). 
Symbolic Link:  A class type used within the source code, such as superclasses, extended interfaces, variables, parameters, return values, instanceofs, and upcasts. 

Class loaders and their usage follow a few simple rules:

  • Class loaders are hierarchically organized, where each one has a parent class loader, except the bootstrap class loader (the root). 
  • Class loaders should (practically: must) delegate the loading of a class to the parent, but a custom class loader can define for itself when it should do so. 
  • A class is defined by its class type and the effective class loader. 
  • A class is only loaded once and then cached in the class loader to ensure that the byte code cannot change. 
  • Any symbolic links are loaded by the effective class loader (or one of its ancestors), if this is not already done. The JVM can defer this resolution until the class is actually used. 
  • An upcast of an instance to another class fails when the class of the instance and the class of the symbolic link do not match (meaning their class loaders do not match). 

  • Now I want to put on some meat to these bare-bone rules to provide better understanding.

    Class Loader Organization and Delegation

    Before we start, let's look at a typical class loader hierarchy, as illustrated by Figure 1:




        As shown in Figure 1, the bootstrap class loader (BS) loads the classes from the JVM, as well as extensions to the JDK. The system class loader (CP) loads all of the classes provided by the CLASSPATH environment variable or passed using the -classpath argument to the java command. Finally we have several additional class loaders, where A1-3 are children of the CP, and B1-2 are children of A3. Every class loader (except BS) has a parent class loader, even if no parent is provided explicitly; in the latter case, the CP is automatically set as the parent. 

        That alone does not mean much but has a big impact on class-loading delegation. The Javadoc of java.lang.ClassLoader specifies that any class loader must first delegate the loading of a class to the parent, and only if this fails does it try to load the class itself. Actually, the class loader does not care about which one gets the bytes of the class, but rather which one calls defineClass(). In this final method, an instance of class java.lang.Class is created and cached in the class loader so that the byte code of a class cannot change on a following request to load the class. This method also checks that the given class name matches the class name in the byte code. Because this method is final, no custom class loader can change this behavior. 

        As previously mentioned, a class loader must delegate the loading of a class (although a developer can override loadClass() and change this behavior). On one hand, if loading of system classes is not delegated, an application could provide malicious code for JDK classes and introduce a ton of problems. On the other hand, all classes at least extend java.lang.Object, and this class must be resolved, too. Thus the custom class loader has to load this class by itself, otherwise the load fails with a linkage error. These two facts imply that a custom class loader has to delegate class loading. In JDK 1.4, two of the three versions of defineClass() throw a SecurityException if the given class name starts with "java", while the third version is deprecated due to these security concerns.

        I want to stress the fact here that there is a difference between the class loader that starts the process of loading the class and the one that actually loads (defines) the class. Assuming that in our example no class loader delegates the loading of a class to one of its children, any class is either loaded by the Initial CL or by one of its ancestors. Let us assume that a class A contains a symbolic link to class B that in turn contains a symbolic link to class C. The class loader of C can never be a child of the class loader of B or of A. Of course, one should never say "never," and yes, it is possible to break this rule, but like multiple inheritance in C++, this is "black belt" programming. 

        A more prominent exception of the JDK delegation model of "delegating first" is the class loader for a web container described in the servlet specification. This one tries to load a class first by itself before it delegates to the parent. Nevertheless, some classes, such as java.*, javax.*, org.xml.sax.* and others, are delegated first to the parent. For more information, please check out the Tomcat 5.0 documentation.


    Class Linking

        After a class is defined with defineClass(), it must be linked in order to be usable by the final resolveClass() method. Between this method call and the first usage of a symbolic link, the class type is loaded by the class loader of the containing class as Initial CL. If any linked class (type) cannot be loaded, the method will throw a linkage error (java.lang.NoClassDefFoundError). Keep in mind that the resolution of symbolic links is up to the JVM and can be done anywhere between the loading of the containing class (eager resolution or C-style) and the first actual usage of the symbolic link (lazy resolution). It can happen that a symbolic link is in a class and if it is never used, the linked class will never be loaded such as in this example with JDK 1.4.2 on Windows 2000:

    public class M {// In JDK 1.4.2 on W2K this class can be used// fine even if class O is not available.public O mMyInstanceOfO;
    }
    
    实际测试环境,Eclipse3.4,JDK6.0,Windows2003,根本无法通过编译!

    whereas this class will fail with a linkage error if the class O cannot be loaded:

    public class M {// In JDK 1.4.2 and W2K the creation of an// instance of M will FAIL with// a NoClassDefFoundError if class O is not// availablepublic O mMyInstanceOfO = new O();
    }
    

    and to make matters a little bit more complicated, it only fails when an instance is created:

        // Fine because in JDK 1.4.2 on W2K class// linking is done lazyClass lClassM = Class.forName("M");// Fails with NoClassDefFoundErrorObject lObject = lClassM.newInstance();
    
    实际测试环境,Eclipse3.4,JDK6.0,Windows2003,找不到 M 类就抛异常了!
    Class lClassM = Class.forName("M");

    For more information, please read Chapter 12: "Execution" in the Java Language Specification.


    Class Definition

        To a beginner, a class is identified solely by the class type. As soon as you start to deal with class loaders, this is no longer the case. Provided that class type M is not available to CP, A1 and A2 could load the same class type M with different byte code. Even when the byte code would be the same from a Java point of view, these classes are different, no matter if the byte code is the same or not. To avoid ambiguities, a class is identified by its class type as well as the Effective CL, and I will use the notation <Class Name>-<Class Loader>. So for this case, we have classes M-A1 and M-A2. Imagine we also have another class, Test-A1, with a method upcastM() that looks like this:

    public void upcastM(Object pInstance) throws Exception {M lM = (M) pInstance;
    }
    
        Because the class Test is loaded by A1, its symbolic link M is also loaded by A1. So we are going to upcast a given object to M-A1. When this method is called with an instance of the class M-A1 as an argument, it will return successfully, but if it is called with an instance of M-A2, it will throw a ClassCastException because it is not the same class, according to the JVM. Even with reflection this rule is enforced, because both java.lang.Class.newInstance() and java.lang.reflect.Constructor.newInstance() return an instance of class java.lang.Object-BS. Unless only reflection is used during the lifetime of this object, the instance has to be upcast at some point. In the case of only using reflection to avoid conflicts, any arguments of a method still be subject to an upcast to the class of the method signature and therefore the classes must match, otherwise you get a java.lang.IllegalArgumentException due to the ClassCastException

        

    Test

        The sample code may help the reader to better understand the concepts described above and, later, to do their own investigations. In order to run the sample code, just extract it in the directory of your choice and execute the ant build script in the classloader.part1.basics directory.(代码 classloader.zip 已上传)

    解压后,cmd 进入build.xml 所在目录,

    >ant  build ---编译

    >ant  main ---编译并执行

    >ant  clean ---删除编译后的文件

        It has three directories: main, version_a, and version_b. The main directory contains the startup class Main.java as well as the custom class loader that will load classes from a given directory. The other two directories both contain one version of M.java and Test.java. The class Main will first create two custom class loaders each loading classes, after delegating to the parent class loader, from either the version_a or version_b directories. Then it will load the class M by each of these two class loaders and create an instance through reflection:

    Main.main():

    // Create two class loaders one for each version
    ClassLoader lClassLoader_A = new MyClassLoader( "./build/classes/version_a" );
    ClassLoader lClassLoader_B = new MyClassLoader( "./build/classes/version_b" );// Load Class M from first CL and create instance
    Object lInstance_M_A = createInstance( lClassLoader_A, "M" );// Load Class M from second CL and create instance
    Object lInstance_M_B = createInstance( lClassLoader_B, "M" );

    Main.createInstance():

    private static Object createInstance( ClassLoader pClassLoader, String pClassName )throws Exception {Class lClass = pClassLoader.loadClass( pClassName );return lClass.newInstance();
    }

    MyClassLoader:

    public class MyClassLoader extends ClassLoader {private String mDirectory;public MyClassLoader(String pDirectory) {super();mDirectory = pDirectory;}protected Class findClass( String pClassName ) throws ClassNotFoundException {try {System.out.println( "Current dir: " + new File( mDirectory ).getAbsolutePath() );File lClassFile = new File( mDirectory, pClassName + ".class" );InputStream lInput = new BufferedInputStream( new FileInputStream( lClassFile ) );ByteArrayOutputStream lOutput = new ByteArrayOutputStream();int i = 0;while( ( i = lInput.read() ) >= 0 ) {lOutput.write( i );}byte[] lBytes = lOutput.toByteArray();return defineClass( pClassName, lBytes, 0, lBytes.length );} catch( Exception e ) {throw new ClassNotFoundException( "Class: " + pClassName + " could not be found" );}}//原作者的代码覆盖了Class loadClass( String pClassName, boolean pResolve )方法//不过一般情况下只需要覆盖findClass方法就OK了!JDK的API文档也是这么说的//原作者在这里覆盖loadClass方法,是为了演示 Main.main()的最后一种情形---lazy loading of classes!
    }

    In order to test an upcast, I need a class where the Effective CL is one of the custom class loaders. I then use reflection in order to invoke a method on them because I cannot upcast them because Main is loaded by the CP:

    Main.main(),接上

    // Check the upcast of a instance of M-A1 to class M-A1
    // This test must succeed because the CLs match.
    try {checkUpcast( lClassLoader_A, lInstance_M_A );System.err.println( "OK: Upcast of instance of M-A1 succeeded to a class of M-A1" );
    } catch (ClassCastException cce) {System.err.println( "ERROR: Upcast of instance of M-A1 failed to a class of M-A1" );
    }// Check the upcast of a instance of M-A2 to class M-A1
    // This test must fail because the CLs does not match.
    try {checkUpcast( lClassLoader_A, lInstance_M_B );System.err.println( "ERROR: upcast of instance of M-A2 succeeded to a class of M-A1" );
    } catch (ClassCastException cce) {System.err.println( "OK: upcast of instance of M-A2 failed to a class of M-A1" );
    }// Check the upcast of a instance of M-A1 to class M-A2
    // This test must fail because the CLs does not match.
    try {checkUpcast( lClassLoader_B, lInstance_M_A );System.err.println( "ERROR: upcast of instance of M-A1 succeeded to a class of M-A2" );
    } catch (ClassCastException cce) {System.err.println( "OK: upcast of instance of M-A1 failed to a class of M-A2" );
    }// Check the upcast of a instance of M-A2 to class M-A2
    // This test must succeed because the CLs match.
    try {checkUpcast( lClassLoader_B, lInstance_M_B );System.err.println( "OK: Upcast of instance of M-A2 succeeded to a class of M-A2" );
    } catch (ClassCastException cce) {System.err.println( "ERROR: Upcast of instance of M-A2 failed to a class of M-A2" );
    }

    The checkUpcast() loads the class Test through reflection and calls the Test.checkUpcast() method, which makes a simple upcast:

    Main.checkUpcast():

    private static void checkUpcast( ClassLoader pTestCL, Object pInstance ) throws Exception {try {Object lTestInstance = createInstance( pTestCL, "Test" );Method lCheckUpcastMethod = lTestInstance.getClass().getMethod("checkUpcast", new Class[] { Object.class } );lCheckUpcastMethod.invoke( lTestInstance, new Object[] { pInstance } );} catch( InvocationTargetException ite ) {throw (ClassCastException) ite.getCause();}
    }

    Afterwards, there are some tests that do the same thing, but check the upcast restriction against reflection to ensure that reflection cannot compromise the rules posted at the beginning of the article. The last test checks the linking of symbolic links. On Windows 2000 and JDK 1.4.2, it will also show the lazy loading of classes because the loading of the class succeeds, whereas the creation of the instance eventually fails:

    实际测试环境,Ant,JDK6.0,Windows2003,lazy loading of classes 依然有效

    try {Class lClassN = ( (MyClassLoader) lClassLoader_A).loadClass( "N", true );//lClassN.newInstance();System.err.println( "ERROR: Linkage error not thrown even class O is not available for class N" );
    } catch( NoClassDefFoundError ncdfe ) {System.err.println( "OK: Linkage error because class O could not be found for class N" );
    }
    如上,注释掉,lClassN.newInstance();

    output:ERROR: Linkage error not thrown even class O is not available for class N


    // Check the upcast of a instance created by reflection. Test loaded by first CL
    // will try to create instance through reflection with the first CL.
    // Upcast should succeed because CLs match.
    try {checkReflection( lClassLoader_A, lClassLoader_A );System.err.println( "OK: Upcast of instance of class M-A1 in Test-A1 succeeded" );
    } catch (ClassCastException cce) {System.err.println( "ERROR: Upcast of instance of class M-A1 in Test-A1 failed" );
    }// Check the upcast of a instance created by reflection. Test loaded by first CL
    // will try to create instance through reflection with the second CL.
    // Upcast must fail because CLs do not match.
    try {checkReflection( lClassLoader_A, lClassLoader_B );System.err.println( "ERROR: Upcast of instance of class M-A2 in Test-A1 succeeded" );
    } catch (ClassCastException cce) {System.err.println( "OK: Upcast of instance of class M-A2 in Test-A1 failed" );
    }// Check if the arguments in a reflection call are upcasted and therefore the class loaders are checked
    // Test must succeed because the CLs do match
    try {Object lTestInstance = createInstance( lClassLoader_A, "Test" );// Use the class M-A1 to find the methodMethod lCheckReflectionMethod = lTestInstance.getClass().getMethod("checkReflectionArgument", new Class[] { lInstance_M_A.getClass() } );// Now hand over an instance of class M-A2lCheckReflectionMethod.invoke( lTestInstance, new Object[] { lInstance_M_A } );System.err.println( "OK: Upcast of instance M-A1 on method argument of class M-A1 succeeded" );
    } catch( Exception e ) {// We are fineSystem.err.println( "ERROR: Upcast of instance M-A1 on method argument of class M-A1 failed" );
    }// Check if the arguments in a reflection call are upcasted and therefore the class loaders are checked
    // Test must fail because the CLs do not match
    try {Object lTestInstance = createInstance( lClassLoader_A, "Test" );// Use the class M-A1 to find the methodMethod lCheckReflectionMethod = lTestInstance.getClass().getMethod("checkReflectionArgument", new Class[] { lInstance_M_A.getClass() } );// Now hand over an instance of class M-A2lCheckReflectionMethod.invoke( lTestInstance, new Object[] { lInstance_M_B } );System.err.println( "ERROR: Upcast of instance M-A2 on method argument of class M-A1 succeeded" );
    } catch( Exception e ) {// We are fineSystem.err.println( "OK: Upcast of instance M-A2 on method argument of class M-A1 failed" );
    }// Load a class N that has a symbolic link to class O that was removed so that the class resolving
    // must fail
    try {// Upcast ClassLoader to our version in order to access the normally protected loadClass() method// with the resolve flag. Even the resolve flag is set to true the missing symbolic link is only// detected in W2K and JDK 1.4.2 when the instance is created.Class lClassN = ( (MyClassLoader) lClassLoader_A).loadClass( "N", true );// Finally when the instance is created any used symbolic link must be resolved and the creation// must faillClassN.newInstance();System.err.println( "ERROR: Linkage error not thrown even class O is not available for class N" );
    } catch( NoClassDefFoundError ncdfe ) {System.err.println( "OK: Linkage error because class O could not be found for class N" );
    }
    Please note that in the directory version_a there is a class named O.java, because in order to compile the class N.java , this class is needed. However, the ant build script will remove the compiled class O.class before the test is started.


    Conclusion

        As long as a Java developer does not deal with his or her own class loader, all of the classes are loaded by the bootstrap and system class loader, and there will never be a conflict. Thus, it seems that a class is defined only by the fully qualified class name. As soon as there are sibling class loaders -- neither a parent of the other -- a class type can be loaded multiple times with or without different byte code. The class loader also defines the visibility of a class type because any upcast checks against the class name as well as its class loaders.

        To use the currency analogy, this is expressed by the fact that you can have several currencies in your wallet, but as soon as you want to use one, the cashier will check if your money is of the local currency. Still, you can carry these currencies in your pocket wherever you go, and likewise, you can carry around instances of classes even when they are unknown or not compatible in a particular class, as long as the class of the reference is compatible there. Luckily in Java, java.lang.Object is the superclass of all instances and is loaded by the BS, which is the parent of all class loaders no matter what. This means a reference of a class java.lang.Object is always compatible. I think of this as a "tunneling through" of classes from one compatible island to the next -- something that is very important in J2EE, as will be shown in a future installment.

        My analogy with the currencies is very simplified, because it implies that all classes have the same visibility due to the single border of a country. The analogy is based on the two-dimensional world map, whereas with Java class loaders, each level within the hierarchy of the class loaders is adding a new layer and building up a three-dimensional space.

        Additional class loaders enable a Java developer to write modular applications where the visibility of classes is restricted, and therefore, multiple class types can be loaded and managed. Nevertheless, it requires effort to understand the used class loaders and the organization of the classes and class loaders. As with threads, class loading is a runtime behavior that is not obviously visible to the developer, and requires experience and testing to understand and utilize.

        Now that the groundwork is laid, we can finally delve into the usage of class loaders. In the next article, we will see how class loaders can be used in a J2EE application server to manage deployments and what the effects are on invocations through local or remote interfaces. Afterwards, we will see how advanced class loaders make it possible to drop class types or massage the code in order to add "Advices" (AOP) at runtime without changing or recompiling your code. 












     



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/498173.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cocos creator -引擎解构

Cocos creator -引擎结构 在长期的开发中&#xff0c;发现cc对大型的手游加载项目的速度很慢&#xff0c;于是我产生了一种想法&#xff0c;想把 cocos creator移植在Linux上做开发&#xff0c;编译时在Windows。但是这样太麻烦了。索性&#xff0c;研究一下它的构造&#xff…

计算机视觉简介:历史、现状和发展趋势

来源&#xff1a;专知 概要&#xff1a;正像其它学科一样&#xff0c;一个大量人员研究了多年的学科&#xff0c;却很难给出一个严格的定义&#xff0c;模式识别如此&#xff0c;目前火热的人工智能如此&#xff0c;计算机视觉亦如此。 【导读】本文由中国科学院自动化研究所模…

MySQL Cookbook 学习笔记-02

1、分组后查找最大或最小值 2、根据“日期-时间”分组 3、“分组计算” 和 “全局计算” 同时存在查询中 4、删除一行数据&#xff0c;sequence 列会重新生成吗&#xff1f; 5、sequence 列指定值插入&#xff0c;不是我认为的不能指定值哦&#xff01; 6、删除最大 sequence 行…

IIS-HTTPS(TSL)强制开启的方法和解决过时的安全问题

IIS-HTTPS(TSL)强制开启的方法和解决过时的安全问题 系统为:Windows server 2008R2 工具为:IIS6 数据库为: Windows Sql server 2014 证书为:腾讯云颁发的AC证书 首先你需要这几个工具 IISCrypto | 检测和为你配置最安全的 策略环境 手写reg注册表 | 来关闭本地的事件 Windo…

AI在医疗行业的最新进展

来源&#xff1a; Future智能 概要&#xff1a;随着人工智能、大数据等相关应用与理念的不断传播&#xff0c;越来越多曾经深入人心的观念被彻底撼动&#xff0c;当然&#xff0c;医疗行业也不例外。 随着人工智能、大数据等相关应用与理念的不断传播&#xff0c;越来越多曾经深…

用jar 命令打包war包

假定有一个Web应用&#xff1a;C:\myHomemyHome/WEB-INF/……myHome/files/……myHome/image/……myHome/src/……myHome/index.jsp在命令行窗口下执行如下命令&#xff1a;C:\>cd myHomeC:\myHome\>jar cvf myhome.war */ .解释&#xff1a;jar cvf [A》 war包…

SHA384-算法解密(2)还原元数据

SHA384-算法解密(2)还原元数据 上一次的讲解比较潦草&#xff0c;这次写的更全面详细一些。 首先各位&#xff0c;如果想要解开使用这个算法加密后的数据&#xff0c;必须先学会加密&#xff0c;才能解密。 声明&#xff1a;这里仅供学习研究&#xff0c;不要学了三脚猫功夫就…

美国《时代》周刊公布年度25大最佳发明名单

来源&#xff1a; 中国智慧城市导刊 概要&#xff1a;除了大名鼎鼎的iPhone X和特斯拉model 3&#xff0c;还有好多你可能还未听过的新奇玩意。 当地时间16日&#xff0c;美国《时代》周刊发布了2017年25大最佳发明名单。除了大名鼎鼎的iPhone X和特斯拉model 3&#xff0c;还有…

顶级隐写术,破坏一切解释器

什么是隐写术&#xff1f; 就编程来说&#xff0c;隐写的信息通过加密或混淆&#xff0c;其内容例如一张购物清单&#xff0c;一篇文章&#xff0c;一篇图画或者其他“伪装”&#xff08;cover&#xff09;的消息。 隐写的信息通常用一些传统的方法进行加密&#xff0c;然后用…

MySQL 字符集相关问题

MySQL安装时指定的字符集为UTF8&#xff0c;但是当我向如下表插入汉字时&#xff0c;总是失败&#xff08;错误字符&#xff09;&#xff01; DROP TABLE IF EXISTS t_weather; create table t_weather (c_id int unsigned not null auto_increment,c_province varchar(20…

“头移植模型”论文称换头术可行 业内疑两大问题未解

来源&#xff1a;澎湃新闻 概要&#xff1a;11月21日&#xff0c;“换头术”的倡导者、哈尔滨医科大学教授任晓平在一场见面会上称&#xff0c;团队在科学领域取得重大突破&#xff0c; “完成了人类第一例头移植外科实验模型”。 11月21日&#xff0c;“换头术”的倡导者、哈尔…

图片有损解构术

图片有损解构 解释&#xff1a;将任意图片解构其PS或修图或雪碧图拼接之前&#xff0c;将通道与法线分离并在原图展现出来 在群里经常看到某些人转发一些图片&#xff0c;有意或者无意的&#xff0c;勾起了我的好奇心&#xff0c;他们这么做有什么好处&#xff1f; 左边图片是…

让机器听懂世界,触及人类梦想还有多远?

来源&#xff1a;陈孝良科学网博客 概要&#xff1a;语言对于人类文明的重要性不言而喻&#xff0c;但是语言的起源却是个高度争议的话题&#xff0c;我们对此几乎一无所知。 语言对于人类文明的重要性不言而喻&#xff0c;但是语言的起源却是个高度争议的话题&#xff0c;我们…

[实战]前端wireshark抓包协议解密

前端wireshark抓包协议解密废话不多说&#xff0c;先看看结果该JSON文件是通过解密后的 HTTP 返回response结果再解密打开的新页面 有兴趣的小伙伴了解下之前的文章 Sha384解密[2] 打开Wireshark 将TCP 转码为RTP &#xff0c;因为该目标地址有视频文件&#xff0c;方便转换 登…

Java异常及处理

java.lang.UnsupportedClassVersionError: Bad version number in .class file java.lang.UnsupportedClassVersionError: Bad version number in .class file 造成这种过错是你的支撑Tomcat运行的JDK版本与支撑application运行的JDK版本不一致导致的. 把它们的JDK版本改成一致…

前端React结构工程-改写render

前端React结构工程-改写render 工程准备事项 npm installcnpm初始化工程实例 以上是实例化&#xff0c;安装过npm后的列表 接下来使用 npm run start 来启动项目 当你启动项目后会看到react给我们准备好的 默认界面 React中的 diff原理 和 调度原理是 这次探索的目标 只有搞…

未来智能实验室成立,建设世界第一个智能系统智商评测和趋势研究机构

来源&#xff1a;未来智能实验室 互联网云脑逐渐清晰&#xff0c;AI与互联网结合引发AI威胁论 从科学史可以看到这样一个规律&#xff1a;每一次人类社会的重大技术变革都会导致新领域的科学革命。互联网革命对于人类的影响已经远远超过了大工业革命。与工业革命增强人类的力量…

WebService相关

学习在线文档&#xff1a;http://www.blogjava.net/nokiaguy/archive/2009/01/archive/2009/01/archive/2009/01/02/249556.html 将wsdl2java命令生成的stub类发布到项目正确的位置 打开 cmd&#xff0c;进入%MyEclipse_WS% 命令如下&#xff1a; wsdl2java -uri http://loc…

自己动手制作一门语言(1)波罗语

自己动手制作一门语言(1)波罗语 波罗语&#xff1a;基于波斯(阿拉伯语)的繁衍&#xff0c;主要目的是二向加密语言。防止被保护的数据泄露和解密。使用在计算机与书本中使用语言的发音 主要以 ah 、v 、hv 颤音、哈音、卷舌 创造一门语言很容易&#xff0c;要实现起来确很难&a…

高盛:人工智能报告中文版(45页)

来源&#xff1a;数据局 概要&#xff1a;人工智能是信息时代的尖端科技。计算的飞跃建立在人类告知计算机如何表现的基础上&#xff0c;计算建立在计算机学习如何表现能够对每个行业有意义的基础上。 人工智能是信息时代的尖端科技。计算的飞跃建立在人类告知计算机如何表现的…