我对Java语言的理解

古城微笑少年丶 2021-10-19 06:46 475阅读 0赞
  1. 去年七月初通过校招进入了现在的公司,转眼已经过去一年多了,经过一年多的实战开发,重新整理一下自己对java的理解,希望能对正在面试以及即将入职工作的blogger有所帮助。

1、平台无关性

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70

  1. Java源码首先被编译成字节码,再由不同的平台的JVM(Java Virtual Machine)进行解析,Java语言在不同的平台上运行时不需要进行重新编译,Java虚拟机在执行字节码的时候,把字节码转换成具体平台上的机器指令。
  2. 下面我们简单看一下jvm执行的字节码,命令 javap
  3. public class T {
  4. public static void main(String[] args) {
  5. int i = 1;
  6. System.out.println(i++);
  7. }
  8. }
  9. 使用 javap查看字节码

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 1

2、JVM加载class文件

  1. JVM如何加载编译好的class文件呢?
  2. Java虚拟机:是一种抽象化的虚拟机,通过在实际计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统,JVM屏蔽了与具体操作系统windowslinux等相关的信息,使得Java程序只需生成在Java虚拟机上运行的代码及字节码,就可以在多种平台上不加修改的运行。
  3. 通常呢,我们不需要知道JVM的运行原理,只需要专注于Java代码就可以了,当然,这也是虚拟机之所以存在的原因,即屏蔽底层操作系统的不同,并且,减少基于原生语言的开发的复杂性。只要虚拟机厂商在特定操作系统上实现了虚拟机,定义如何将字节码解析成本操作系统可执行的二进制码,java语言便能跨越各种的平台。
  4. JVM的架构 = Class Loader + Runtime Data Access + Execution Engine + Native Interface

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 2

  1. Class Loader: 依据特定格式,加载class文件到内存。
  2. Execution Engine: 对命令进行解析,即解析class文件中的字节码,解析完成之后,提交操作系统执行。
  3. Runtime Data Area: JVM内存空间结构模型,我们所写的程序都会被加载到这里,之后才开始运行。
  4. Native Interface: 融合不同开发语言的原生库为Java所用,JVM开辟了一块区域用来专门处理标记为native的代码,具体做法是,在Native Method Stack中登记native方法,在Excution执行时,加载Native Libraries
  5. Class.forName中调用的forName0
  6. /**
  7. * Returns the {@code Class} object associated with the class or
  8. * interface with the given string name. Invoking this method is
  9. * equivalent to:
  10. *
  11. * <blockquote>
  12. * {@code Class.forName(className, true, currentLoader)}
  13. * </blockquote>
  14. *
  15. * where {@code currentLoader} denotes the defining class loader of
  16. * the current class.
  17. *
  18. * <p> For example, the following code fragment returns the
  19. * runtime {@code Class} descriptor for the class named
  20. * {@code java.lang.Thread}:
  21. *
  22. * <blockquote>
  23. * {@code Class t = Class.forName("java.lang.Thread")}
  24. * </blockquote>
  25. * <p>
  26. * A call to {@code forName("X")} causes the class named
  27. * {@code X} to be initialized.
  28. *
  29. * @param className the fully qualified name of the desired class.
  30. * @return the {@code Class} object for the class with the
  31. * specified name.
  32. * @exception LinkageError if the linkage fails
  33. * @exception ExceptionInInitializerError if the initialization provoked
  34. * by this method fails
  35. * @exception ClassNotFoundException if the class cannot be located
  36. */
  37. @CallerSensitive
  38. public static Class<?> forName(String className)
  39. throws ClassNotFoundException {
  40. Class<?> caller = Reflection.getCallerClass();
  41. return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
  42. }
  43. /** Called after security check for system loader access checks have been made. */
  44. private static native Class<?> forName0(String name, boolean initialize,
  45. ClassLoader loader,
  46. Class<?> caller)
  47. throws ClassNotFoundException;

3、谈谈反射

  1. Java反射机制是在运行状态中,对任意一个类,都能够知道这个类的所有属性和方法;对任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
  2. 简单例子
  3. public class Dog {
  4. private String name;
  5. public void sayHi(String hi) {
  6. System.out.println(hi + " " + name);
  7. }
  8. private String returnHello(String hello) {
  9. return hello;
  10. }
  11. }
  12. public class ReflectDemo {
  13. public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
  14. Class c = Class.forName("Dog");
  15. if(!c.isAssignableFrom(Dog.class))
  16. return ;
  17. Dog dog = (Dog) c.newInstance();
  18. System.out.println("Class name is " + c.getName());
  19. Method returnHello = c.getDeclaredMethod("returnHello", String.class);
  20. returnHello.setAccessible(true);
  21. String str = (String) returnHello.invoke(dog, "ao wu");
  22. System.out.println(str);
  23. Method sayHi = c.getMethod("sayHi", String.class);
  24. sayHi.invoke(dog, "hi");
  25. Field name = c.getDeclaredField("name");
  26. name.setAccessible(true);
  27. name.set(dog, "Doge");
  28. sayHi.invoke(dog, "hi");
  29. }
  30. }
  31. 编译运行
  32. Class name is Dog
  33. ao wu
  34. hi null
  35. hi Doge
  36. 通过这个例子,我们可以知道,反射就是把Java类中的各种成分映射成一个个Java对象,MethodFieldClass

4、ClassLoader

  1. 在上面我们之所以能够获得类的属性或者方法,并对其进行调用,必须要获取Class对象,而要获取该类的Class对象必先获取该类所对应字节码文件对象。
  2. 编译器将Dog.java源文件编译成Dog.class字节码文件。
  3. ClassLoader将字节码转换成JVM中的Class<Dog>对象。
  4. JVM利用Class<Dog>对象实例化为Dog对象。
  5. ClassLoader: ClassLoaderJava中有着非常重要的作用,它主要工作在Class装载的加载阶段,其主要作用是从系统外部获得Class二进制数据流。它是Java的核心组件,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过将Class文件里的二进制数据流装进系统,然后交给Java虚拟机进行连接、初始化等操作。
  6. ClassLoader的种类
  7. BootStrapClassLoader: C++编写,加载Java自带的核心类库java.\*,比如java.lang包。
  8. ExtClassLoader: Java编写,加载扩展库javax.\*,加载位于jre/lib/ext目录下的jar包。
  9. AppClassLoader: Java编写,加载程序所在目录。
  10. 自定义ClassLoader: Java编写,定制化加载。
  11. 我们可以看一下ExtClassLoader的代码
  12. private static File[] getExtDirs() {
  13. String var0 = System.getProperty("java.ext.dirs");
  14. File[] var1;
  15. if (var0 != null) {
  16. StringTokenizer var2 = new StringTokenizer(var0, File.pathSeparator);
  17. int var3 = var2.countTokens();
  18. var1 = new File[var3];
  19. for(int var4 = 0; var4 < var3; ++var4) {
  20. var1[var4] = new File(var2.nextToken());
  21. }
  22. } else {
  23. var1 = new File[0];
  24. }
  25. return var1;
  26. }
  27. 可以看一下 "java.ext.dirs" 的路径
  28. System.out.println(System.getProperty("java.ext.dirs"));
  29. C:\ProgramFiles\Java\jdk1.8.0_131\jre\lib\ext;
  30. C:\Windows\Sun\Java\lib\ext
  31. 我们可以看一下AppClassLoader的代码
  32. public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
  33. final String var1 = System.getProperty("java.class.path");
  34. final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
  35. return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
  36. public Launcher.AppClassLoader run() {
  37. URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
  38. return new Launcher.AppClassLoader(var1x, var0);
  39. }
  40. });
  41. }
  42. 可以看一下 "java.class.path" 的路径
  43. System.out.println(System.getProperty("java.class.path"));
  44. C:\Program Files\Java\jdk1.8.0_131\jre\lib\charsets.jar;
  45. C:\Program Files\Java\jdk1.8.0_131\jre\lib\deploy.jar;
  46. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\access-bridge-64.jar;
  47. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\cldrdata.jar;
  48. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\dnsns.jar;
  49. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jaccess.jar;
  50. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\jfxrt.jar;
  51. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\localedata.jar
  52. ;C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\nashorn.jar;
  53. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunec.jar;
  54. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunjce_provider.jar;
  55. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunmscapi.jar;
  56. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\sunpkcs11.jar;
  57. C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext\zipfs.jar;
  58. C:\Program Files\Java\jdk1.8.0_131\jre\lib\javaws.jar;
  59. C:\Program Files\Java\jdk1.8.0_131\jre\lib\jce.jar;
  60. C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfr.jar;
  61. C:\Program Files\Java\jdk1.8.0_131\jre\lib\jfxswt.jar;
  62. C:\Program Files\Java\jdk1.8.0_131\jre\lib\jsse.jar;
  63. C:\Program Files\Java\jdk1.8.0_131\jre\lib\management-agent.jar;
  64. C:\Program Files\Java\jdk1.8.0_131\jre\lib\plugin.jar;
  65. C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;
  66. C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;
  67. D:\IdeaProjects\JavaStudy\target\classes;
  68. D:\maven\repository\org\projectlombok\lombok\1.18.4\lombok-1.18.4.jar;
  69. D:\maven\repository\org\springframework\boot\spring-boot-starter-security\2.1.6.RELEASE\spring-boot-starter-security-2.1.6.RELEASE.jar;
  70. D:\maven\repository\org\springframework\boot\spring-boot-starter\2.1.6.RELEASE\spring-boot-starter-2.1.6.RELEASE.jar;
  71. D:\maven\repository\org\springframework\boot\spring-boot\2.1.6.RELEASE\spring-boot-2.1.6.RELEASE.jar;
  72. D:\maven\repository\org\springframework\boot\spring-boot-autoconfigure\2.1.6.RELEASE\spring-boot-autoconfigure-2.1.6.RELEASE.jar;
  73. D:\maven\repository\org\springframework\boot\spring-boot-starter-logging\2.1.6.RELEASE\spring-boot-starter-logging-2.1.6.RELEASE.jar;
  74. D:\maven\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;
  75. D:\maven\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;
  76. D:\maven\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;
  77. D:\maven\repository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;
  78. D:\maven\repository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;D:\maven\repository\org\slf4j\jul-to-slf4j\1.7.26\jul-to-slf4j-1.7.26.jar;
  79. D:\maven\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;
  80. D:\maven\repository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;D:\maven\repository\org\springframework\spring-aop\5.1.8.RELEASE\spring-aop-5.1.8.RELEASE.jar;
  81. D:\maven\repository\org\springframework\spring-beans\5.1.8.RELEASE\spring-beans-5.1.8.RELEASE.jar;
  82. D:\maven\repository\org\springframework\security\spring-security-config\5.1.5.RELEASE\spring-security-config-5.1.5.RELEASE.jar;
  83. D:\maven\repository\org\springframework\security\spring-security-core\5.1.5.RELEASE\spring-security-core-5.1.5.RELEASE.jar;
  84. D:\maven\repository\org\springframework\spring-context\5.1.6.RELEASE\spring-context-5.1.6.RELEASE.jar;
  85. D:\maven\repository\org\springframework\security\spring-security-web\5.1.5.RELEASE\spring-security-web-5.1.5.RELEASE.jar;
  86. D:\maven\repository\org\springframework\spring-expression\5.1.6.RELEASE\spring-expression-5.1.6.RELEASE.jar;
  87. D:\maven\repository\org\springframework\spring-web\5.1.6.RELEASE\spring-web-5.1.6.RELEASE.jar;
  88. D:\maven\repository\org\springframework\spring-core\5.1.5.RELEASE\spring-core-5.1.5.RELEASE.jar;
  89. D:\maven\repository\org\springframework\spring-jcl\5.1.5.RELEASE\spring-jcl-5.1.5.RELEASE.jar;
  90. C:\Program Files\JetBrains\IntelliJ IDEA 2018.2.1\lib\idea_rt.jar
  91. 自定义ClassLoader的实现
  92. 关键函数 findClassdefineClass
  93. /**
  94. * Finds the class with the specified <a href="#name">binary name</a>.
  95. * This method should be overridden by class loader implementations that
  96. * follow the delegation model for loading classes, and will be invoked by
  97. * the {@link #loadClass <tt>loadClass</tt>} method after checking the
  98. * parent class loader for the requested class. The default implementation
  99. * throws a <tt>ClassNotFoundException</tt>.
  100. *
  101. * @param name
  102. * The <a href="#name">binary name</a> of the class
  103. *
  104. * @return The resulting <tt>Class</tt> object
  105. *
  106. * @throws ClassNotFoundException
  107. * If the class could not be found
  108. *
  109. * @since 1.2
  110. */
  111. protected Class<?> findClass(String name) throws ClassNotFoundException {
  112. throw new ClassNotFoundException(name);
  113. }
  114. /**
  115. * Converts an array of bytes into an instance of class <tt>Class</tt>.
  116. * Before the <tt>Class</tt> can be used it must be resolved.
  117. *
  118. * <p> This method assigns a default {@link java.security.ProtectionDomain
  119. * <tt>ProtectionDomain</tt>} to the newly defined class. The
  120. * <tt>ProtectionDomain</tt> is effectively granted the same set of
  121. * permissions returned when {@link
  122. * java.security.Policy#getPermissions(java.security.CodeSource)
  123. * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}
  124. * is invoked. The default domain is created on the first invocation of
  125. * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},
  126. * and re-used on subsequent invocations.
  127. *
  128. * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use
  129. * the {@link #defineClass(String, byte[], int, int,
  130. * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a
  131. * <tt>ProtectionDomain</tt> as one of its arguments. </p>
  132. *
  133. * @param name
  134. * The expected <a href="#name">binary name</a> of the class, or
  135. * <tt>null</tt> if not known
  136. *
  137. * @param b
  138. * The bytes that make up the class data. The bytes in positions
  139. * <tt>off</tt> through <tt>off+len-1</tt> should have the format
  140. * of a valid class file as defined by
  141. * <cite>The Java™ Virtual Machine Specification</cite>.
  142. *
  143. * @param off
  144. * The start offset in <tt>b</tt> of the class data
  145. *
  146. * @param len
  147. * The length of the class data
  148. *
  149. * @return The <tt>Class</tt> object that was created from the specified
  150. * class data.
  151. *
  152. * @throws ClassFormatError
  153. * If the data did not contain a valid class
  154. *
  155. * @throws IndexOutOfBoundsException
  156. * If either <tt>off</tt> or <tt>len</tt> is negative, or if
  157. * <tt>off+len</tt> is greater than <tt>b.length</tt>.
  158. *
  159. * @throws SecurityException
  160. * If an attempt is made to add this class to a package that
  161. * contains classes that were signed by a different set of
  162. * certificates than this class (which is unsigned), or if
  163. * <tt>name</tt> begins with "<tt>java.</tt>".
  164. *
  165. * @see #loadClass(String, boolean)
  166. * @see #resolveClass(Class)
  167. * @see java.security.CodeSource
  168. * @see java.security.SecureClassLoader
  169. *
  170. * @since 1.1
  171. */
  172. protected final Class<?> defineClass(String name, byte[] b, int off, int len)
  173. throws ClassFormatError
  174. {
  175. return defineClass(name, b, off, len, null);
  176. }
  177. 自定义装载简单demo
  178. public class T {
  179. static {
  180. System.out.println("Hello I'm T");
  181. }
  182. }
  183. import java.io.*;
  184. public class MyClassLoader extends ClassLoader {
  185. private String path;
  186. private String classLoadername;
  187. public MyClassLoader(String path, String classLoadername) {
  188. this.path = path;
  189. this.classLoadername = classLoadername;
  190. }
  191. @Override
  192. protected Class<?> findClass(String name) throws ClassNotFoundException {
  193. byte[] bytes = classLoaderName(name);
  194. return defineClass(name, bytes, 0, bytes.length);
  195. }
  196. private byte[] classLoaderName(String name) {
  197. name = path + name + ".class";
  198. InputStream in = null;
  199. ByteArrayOutputStream out = null;
  200. try {
  201. in = new FileInputStream(new File(name));
  202. out = new ByteArrayOutputStream();
  203. int i = 0;
  204. while((i = in.read()) != -1) {
  205. out.write(i);
  206. }
  207. } catch (IOException e) {
  208. e.printStackTrace();
  209. } finally {
  210. try {
  211. out.close();
  212. in.close();
  213. } catch (IOException e) {
  214. e.printStackTrace();
  215. }
  216. }
  217. return out.toByteArray();
  218. }
  219. public String getClassLoadername() {
  220. return classLoadername;
  221. }
  222. public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
  223. MyClassLoader myClassLoader = new MyClassLoader("C:\\Users\\Administrator\\Desktop\\", "myClassLoader");
  224. Class c = myClassLoader.loadClass("T");
  225. System.out.println(myClassLoader.getClassLoadername());
  226. System.out.println(myClassLoader.getParent());
  227. System.out.println(myClassLoader.getParent().getParent());
  228. System.out.println(myClassLoader.getParent().getParent().getParent());
  229. c.newInstance();
  230. }
  231. }
  232. 运行测试main函数
  233. myClassLoader
  234. sun.misc.Launcher$AppClassLoader@18b4aac2
  235. sun.misc.Launcher$ExtClassLoader@5ca881b5
  236. null
  237. Hello I'm T
  238. 进程完成,退出码 0

5、类加载器的双亲委派机制

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 3

  1. 不同ClassLoader加载路径不同,逻辑明确,为了实现分工,各自负责各自的区块。
  2. ClassLoaderloadClass源码如下,感兴趣可以了解一下。
  3. /**
  4. * Loads the class with the specified <a href="#name">binary name</a>. The
  5. * default implementation of this method searches for classes in the
  6. * following order:
  7. *
  8. * <ol>
  9. *
  10. * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
  11. * has already been loaded. </p></li>
  12. *
  13. * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
  14. * on the parent class loader. If the parent is <tt>null</tt> the class
  15. * loader built-in to the virtual machine is used, instead. </p></li>
  16. *
  17. * <li><p> Invoke the {@link #findClass(String)} method to find the
  18. * class. </p></li>
  19. *
  20. * </ol>
  21. *
  22. * <p> If the class was found using the above steps, and the
  23. * <tt>resolve</tt> flag is true, this method will then invoke the {@link
  24. * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
  25. *
  26. * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
  27. * #findClass(String)}, rather than this method. </p>
  28. *
  29. * <p> Unless overridden, this method synchronizes on the result of
  30. * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
  31. * during the entire class loading process.
  32. *
  33. * @param name
  34. * The <a href="#name">binary name</a> of the class
  35. *
  36. * @param resolve
  37. * If <tt>true</tt> then resolve the class
  38. *
  39. * @return The resulting <tt>Class</tt> object
  40. *
  41. * @throws ClassNotFoundException
  42. * If the class could not be found
  43. */
  44. protected Class<?> loadClass(String name, boolean resolve)
  45. throws ClassNotFoundException
  46. {
  47. synchronized (getClassLoadingLock(name)) {
  48. // First, check if the class has already been loaded
  49. Class<?> c = findLoadedClass(name);
  50. if (c == null) {
  51. long t0 = System.nanoTime();
  52. try {
  53. if (parent != null) {
  54. c = parent.loadClass(name, false);
  55. } else {
  56. c = findBootstrapClassOrNull(name);
  57. }
  58. } catch (ClassNotFoundException e) {
  59. // ClassNotFoundException thrown if class not found
  60. // from the non-null parent class loader
  61. }
  62. if (c == null) {
  63. // If still not found, then invoke findClass in order
  64. // to find the class.
  65. long t1 = System.nanoTime();
  66. c = findClass(name);
  67. // this is the defining class loader; record the stats
  68. sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
  69. sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
  70. sun.misc.PerfCounter.getFindClasses().increment();
  71. }
  72. }
  73. if (resolve) {
  74. resolveClass(c);
  75. }
  76. return c;
  77. }
  78. }
  79. 自底向上检查名字为name的类是否已被装载,如果没有,自顶向下装载名字为name的类,关键代码如下:
  80. if (parent != null) {
  81. c = parent.loadClass(name, false);
  82. } else {
  83. c = findBootstrapClassOrNull(name);
  84. }
  85. 上述代码也正可以和输出结果做对比,当parentnull时,则会调用我们的BootStrapClassLoader
  86. myClassLoader
  87. sun.misc.Launcher$AppClassLoader@18b4aac2
  88. sun.misc.Launcher$ExtClassLoader@5ca881b5
  89. null
  90. Hello I'm T
  91. 进程完成,退出码 0
  92. // return null if not found
  93. private native Class<?> findBootstrapClass(String name);
  94. 注意,findBootstrapClass为native标记的方法,在运行时,会调用本地库或外置的非Java代码。
  95. 如何确定findBootstrapClass为C++代码呢?查看网址[http://hg.openjdk.java.net/][http_hg.openjdk.java.net],一下为ClassLoader.c截图

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 4

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 5

  1. 查看源码之后,再来回答一下,为什么要使用双亲委派机制:避免多分同样字节码的加载。

6、loadClass和forName的区别

  1. 隐式加载: new,隐式调用类加载器,加载对应类,创建对应实例。
  2. 显式加载: loadClassforName等,显式加载构建Class对象,然后调用ClassnewInstance创建实例。
  3. loadClassforName 都能知道该类的所有属性和方法,对于任一对象都能调用它的任意防范和属性。
  4. loadClass ClassLoader.loadClass得到的class是还没有链接的。
  5. forName Class.forName得到的class是已经初始化完成的。
  6. 类的装载过程

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 6

  1. 来看一下下面的小demo
  2. public class T {
  3. static {
  4. System.out.println("Hello I'm T");
  5. }
  6. }
  7. public class T2 {
  8. public static void main(String[] args) throws ClassNotFoundException {
  9. System.out.println("我是ClassLoader.loadClass");
  10. ClassLoader cl = T.class.getClassLoader();
  11. Class<T> tLoadClass = (Class<T>) cl.loadClass("T");
  12. System.out.println("我是Class.forName");
  13. Class<T> tForName = (Class<T>) Class.forName("T");
  14. }
  15. }
  16. 运行T2main方法:
  17. 我是ClassLoader.loadClass
  18. 我是Class.forName
  19. Hello I'm T
  20. 从上述执行结果,我们可知道,Class.forName得到的class是已经初始化完成的,ClassLoader.loadClass得到的class是还没有链接的。比如,我们在程序中要加载我们的数据库驱动Driver,我们要使Class.forName。而为什么还会有ClassLoader.loadClass,主要是与LazyLoading有关,ClassLoader.loadClass不需要执行类的链接和初始化,加快了初始化速度。

7、Java的内存模型

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 7

  1. 线程私有:程序计数器、虚拟机栈、本地方法栈。
  2. 线程共享:MetaSpaceJava堆。
  3. Java虚拟机栈(Stack)
  4. Java方法执行的内存模型。
  5. 包含多个栈帧。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 8

  1. 局部变量表和操作数栈
  2. 局部变量表:包含方法执行过程中的所有变量。
  3. 操作数栈:入栈、出栈、复制、交换、产生消费变量。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzM3NzMyODI5_size_16_color_FFFFFF_t_70 9

  1. 递归为什么会引发 java.lang.StackOverflowError 异常: 当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压入虚拟机栈中,当方法执行完,便会将栈帧出栈,因此可知,线程当前执行的方法对应的栈帧位于Java栈的顶部,而我们的递归函数不断的去调用自身,每一次方法调用会涉及:(1)每新调用一个方法就会生成一个栈帧;(2)会保存当前方法的栈帧状态,将它放在虚拟机栈中;(3)栈帧上下文切换,会切换到最新的方法栈中,而我们每个虚拟机栈是固定的,递归过深,栈帧数超过虚拟机栈深度。解决思路:(1)限制递归次数;(2)使用循环替换递归等等。
  2. 虚拟机栈过多引发 java.lang.OutOfMemoryError异常: 当虚拟机栈可以动态扩展时,如果无法申请足够多的内存,就会抛出这个异常。
  3. public void stackLeakByThread() {
  4. while(true) {
  5. new Thread(() -> {
  6. while(true) {}
  7. }).start();
  8. }
  9. }
  10. 本地方法栈
  11. 与虚拟机相似,主要作用于标注了native的方法。
  12. 元空间(MetaSpace)与永久代(PermGen
  13. 存储class的相关信息,包括classmethodfield等等,两者均是方法区的实现,方法区知识JVM的一种规范。Java1.7之后,原先位于方法区中的字符串常量池已被移动到了Java堆当中,并且,1.8之后,使用元空间替代了永久代。 元空间使用本地内存,而永久代使用的是jvm的内存。
  14. Java堆(Heap
  15. 对象实例的分配区域
  16. GC管理的主要区域

发表评论

表情:
评论列表 (有 0 条评论,475人围观)

还没有评论,来说两句吧...

相关阅读

    相关 软件工程理解

    最近在重学软件工程相关的知识,一方面是对自己过往工作经历的一个梳理总结;另一方面,是在和同行交流过程中,发现自己对于一些知识的理解还存在不足。后续一段时间的文章内容,会以软件工

    相关 谈谈协程理解

    协程相关视频解析: [linux系统下协程的实现与原理剖析训练营(上)][linux] [linux系统下协程的实现与原理剖析训练营(下)][linux 1] 什

    相关 BFC理解

      最初这篇文章打算回答寒冬大神的[第一问][Link 1],谈谈CSS布局。本来呢我以为布局主要涉及float跟display相关属性,以及他们的包含框、静态位置等等。后来看

    相关 模块化理解

    模块化是一个"发现" 模块化(Modularity)这个概念与其说是一种创新,不如说是一个"发现"。这正是人们在解决问题时常用的行为方式和思维过程。它不是单纯的技术问题,

    相关 Java语言理解

            去年七月初通过校招进入了现在的公司,转眼已经过去一年多了,经过一年多的实战开发,重新整理一下自己对java的理解,希望能对正在面试以及即将入职工作的blogge

    相关 虚函数理解

           虚函数是具备这样一种能力的函数:能够在知道少量信息的情况下判断出自己的所属者,进而调用所属者里对应的函数。以虚析构函数为例解释下,当我们释放一个用基类的指针指向派