类加载的一个问题!

问题描述

类是在其任何static成员被访问时加载的。我一开始理解的就是试图访问main()(一个static方法),于是加载器开始启动并找出该类的编译代码(在同名class文件之中)。可是有这样一种情况:当运行程序一遍后,注释掉main(),然后再运行程序,会发现似乎加载过程同样发生了:静态变量进行了初始化,然后抛出异常java.lang.NoSuchMethodError:main。当然,这应该是假象。因为这种情况的前提是运行程序一遍后,注释掉main()。而在正常情况下,没有main(),程序根本是无法运行的。谁能告诉这种情况的原因是什么?PS:我用的开发工具是eclipse。

解决方案

解决方案二:
“类是在其任何static成员被访问时加载的”这句话是错的,不知你从哪里听来的。应该说:“如果一个类还没有被加载,那么它会在其任何static成员被访问时加载”。访问static成员确实是加载类的一种方式,但绝不是唯一方式。当你试图用"java<类名>"的方式来启动一个程序时,JVM会首先加载该类,再试图在其中寻找main()方法。
解决方案三:
类是在其任何static成员被访问时加载的哪里听来的??只能说static成员是在类被加载的时候加载还有main只是程序入口,并不是类加载时机main本身只是一个方法,如果类没有被加载,此方法何来运行之说?
解决方案四:
引用1楼dan1980的回复:

“类是在其任何static成员被访问时加载的”这句话是错的,不知你从哪里听来的。应该说:“如果一个类还没有被加载,那么它会在其任何static成员被访问时加载”。访问static成员确实是加载类的一种方式,但绝不是唯一方式。当你试图用"java<类名>"的方式来启动一个程序时,JVM会首先加载该类,再试图在其中寻找main()方法。

“类是在其任何static成员被访问时加载的”这句原话出自ThinkingInJava4th。再看看原文中说的:在Beetle上运行Java时,所发生的第一件事情就是试图访问Beetle.main()(一个static方法),于是加载器开始启动并找出Beetle类的编译代码(在名为Beetle.class的文件中)。……我迷惑了。dan1980兄能介绍一下加载类的不同方式吗?先谢过了。
解决方案五:
引用2楼beiouwolf的回复:

类是在其任何static成员被访问时加载的哪里听来的??只能说static成员是在类被加载的时候加载还有main只是程序入口,并不是类加载时机main本身只是一个方法,如果类没有被加载,此方法何来运行之说?

我对类加载的开始还是比较雾水的。的确,如果类没有加载,main()如何运行?但是我的问题是:注释掉main()方法,为什么会出现静态变量的加载,然后是异常java.lang.NoSuchMethodError:main。也许这些假象都是JVM在作祟。
解决方案六:
引用3楼tequliapop的回复:

引用1楼dan1980的回复:“类是在其任何static成员被访问时加载的”这句话是错的,不知你从哪里听来的。应该说:“如果一个类还没有被加载,那么它会在其任何static成员被访问时加载”。访问static成员确实是加载类的一种方式,但绝不是唯一方式。当你试图用"java<类名>"的方式来启动一个程序时,JVM会首先加载该类,再试图在其中寻找main()方法。“类是在其任何static成员被访问时加载的”这句原话出自ThinkingInJava4th。再看看原文中说的:在Beetle上运行Java时,所发生的第一件事情就是试图访问Beetle.main()(一个static方法),于是加载器开始启动并找出Beetle类的编译代码(在名为Beetle.class的文件中)。……我迷惑了。dan1980兄能介绍一下加载类的不同方式吗?先谢过了。

我相信ThinkingInJava上没有这句话,请指出具体章节,我回头去查。造成类被加载的情况太多了,最简单的:创建一个类的对象就必须先加载该类;另外,超类在其派生类被加载之前自动加载;主程序对应的类由JVM自动加载(当然也包括它的所有超类);运行Applet时,Applet类(以及它的所有超类)也是JVM自动加载的。JVM第一次启动时还会加载很多所需的类,只不过它们都在后台运行,你不察觉罢了。程序员还可以手动加载类,使用Class.forName()方法。不管类以何种方式加载,有一点是肯定的:访问类的成员一定是发生是类加载之后的。每个类都只加载一次,而且类的加载是系统行为,你通常无法控制。系统会保证你在使用任何一个类之前它已经成功加载。所以,“类是在其任何static成员被访问时加载的”或许应该说成“类是在其任何static成员被访问之前加载的”,而且,不总是在紧接着的之前。因为类只加载一次,访问static成员时,它很可能早就加载完毕了(从而不再被加载),也或许它还没有被加载,于是系统先加载类,加载完毕后再返回你要访问的成员。
解决方案七:
恩,学到了东西
解决方案八:
没看明白是什么。呵呵。
解决方案九:
学习了!
解决方案十:
只有在类首次被主动使用时就会加载,静态方法,静态字段被首次条用,反射,序列化等等一共六种
解决方案十一:
引用5楼dan1980的回复:

引用3楼tequliapop的回复:引用1楼dan1980的回复:“类是在其任何static成员被访问时加载的”这句话是错的,不知你从哪里听来的。应该说:“如果一个类还没有被加载,那么它会在其任何static成员被访问时加载”。访问static成员确实是加载类的一种方式,但绝不是唯一方式。当你试图用"java <类名>"的方式来启动一个程序时,JVM会首先加载该类,再试图在其中寻找main()方法。“类是在其任何static成员被访问时加载的”这句原话出自ThinkingInJava4th。再看看原文中说的:在Beetle上运行Java时,所发生的第一件事情就是试图访问Beetle.main()(一个static方法),于是加载器开始启动并找出Beetle类的编译代码(在名为Beetle.class的文件中)。……我迷惑了。dan1980兄能介绍一下加载类的不同方式吗?先谢过了。我相信ThinkingInJava上没有这句话,请指出具体章节,我回头去查。造成类被加载的情况太多了,最简单的:创建一个类的对象就必须先加载该类;另外,超类在其派生类被加载之前自动加载;主程序对应的类由JVM自动加载(当然也包括它的所有超类);运行Applet时,Applet类(以及它的所有超类)也是JVM自动加载的。JVM第一次启动时还会加载很多所需的类,只不过它们都在后台运行,你不察觉罢了。程序员还可以手动加载类,使用Class.forName()方法。不管类以何种方式加载,有一点是肯定的:访问类的成员一定是发生是类加载之后的。每个类都只加载一次,而且类的加载是系统行为,你通常无法控制。系统会保证你在使用任何一个类之前它已经成功加载。所以,“类是在其任何static成员被访问时加载的”或许应该说成“类是在其任何static成员被访问之前加载的”,而且,不总是在紧接着的之前。因为类只加载一次,访问static成员时,它很可能早就加载完毕了(从而不再被加载),也或许它还没有被加载,于是系统先加载类,加载完毕后再返回你要访问的成员。

原话出自Thinginginjava4thP146的注解。我自己还得想想。
解决方案十二:
引用5楼dan1980的回复:

引用3楼tequliapop的回复:引用1楼dan1980的回复:“类是在其任何static成员被访问时加载的”这句话是错的,不知你从哪里听来的。应该说:“如果一个类还没有被加载,那么它会在其任何static成员被访问时加载”。访问static成员确实是加载类的一种方式,但绝不是唯一方式。当你试图用"java <类名>"的方式来启动一个程序时,JVM会首先加载该类,再试图在其中寻找main()方法。“类是在其任何static成员被访问时加载的”这句原话出自ThinkingInJava4th。再看看原文中说的:在Beetle上运行Java时,所发生的第一件事情就是试图访问Beetle.main()(一个static方法),于是加载器开始启动并找出Beetle类的编译代码(在名为Beetle.class的文件中)。……我迷惑了。dan1980兄能介绍一下加载类的不同方式吗?先谢过了。我相信ThinkingInJava上没有这句话,请指出具体章节,我回头去查。造成类被加载的情况太多了,最简单的:创建一个类的对象就必须先加载该类;另外,超类在其派生类被加载之前自动加载;主程序对应的类由JVM自动加载(当然也包括它的所有超类);运行Applet时,Applet类(以及它的所有超类)也是JVM自动加载的。JVM第一次启动时还会加载很多所需的类,只不过它们都在后台运行,你不察觉罢了。程序员还可以手动加载类,使用Class.forName()方法。不管类以何种方式加载,有一点是肯定的:访问类的成员一定是发生是类加载之后的。每个类都只加载一次,而且类的加载是系统行为,你通常无法控制。系统会保证你在使用任何一个类之前它已经成功加载。所以,“类是在其任何static成员被访问时加载的”或许应该说成“类是在其任何static成员被访问之前加载的”,而且,不总是在紧接着的之前。因为类只加载一次,访问static成员时,它很可能早就加载完毕了(从而不再被加载),也或许它还没有被加载,于是系统先加载类,加载完毕后再返回你要访问的成员。

5楼正解.楼主你找不到main方法是因为你调用的启动类必须含有main方法。与类加载机制没有关系。
解决方案十三:
main方法是java程序的入口方法,没有的话,当然不能运行了~~~

时间: 2024-08-03 20:45:59

类加载的一个问题!的相关文章

JVM学习笔记(三)——虚拟机类加载机制

在介绍完class文件格式后,我们来看下虚拟机是如何把一个由class文件描述的类加载到内存中的.具体来说java中类的加载涉及7个阶段:加载.校验.准备.解析.初始化.使用.卸载. 1.加载时机 并不是所有的类在程序启动时即被加载,为提升效率,虚拟机通常秉承的是按需加载的原则,即需要使用到相应的类时才加载对应的类.具体包括如下几个加载时机: 遇到new.getstatic.putstatic.invokestatic这4条指令时,如果对应的类没有被加载,虚拟机会首先加载对应的类.这4条指令对应

Java Reflection(十二):动态类加载与重载

原文地址作者: Jakob Jenkov 译者:叶文海(yewenhai@gmail.com) 内容索引类加载器类加载体系类加载动态类加载动态类重载自定义类重载类加载/重载示例 Java允许你在运行期动态加载和重载类,但是这个功能并没有像人们希望的那么简单直接.这篇文章将阐述在Java中如何加载以及重载类. 你可能会质疑为什么Java动态类加载特性是Java反射机制的一部分而不是Java核心平台的一部分.不管怎样,这篇文章被放到了Java反射系列里面而且也没有更好的系列来包含它了. 类加载器 所

Java SE 6在Solaris的可观察性特征分析

Java平台标准版(Java SE)6,代码名为"Mustang",是最新的Java SE发行版本(正在开发中).Java SE 6源码和二进制代码都可以在www.Java.net上下载.Java SE 6平台要到2006年秋天才能正式发布.不过,现在你可以下载试用Java SE 6 Beta版. Java SE 6平台中提供了多种可观察性(observability)工具,这其中的许多工具都可在系统中运行,而这些工具中的只有极少数被用于挂起进程或核心复制处理.因此,在本文中,我们将分

深入探索Java热部署

简介 在 Java 开发领域,热部署一直是一个难以解决的问题,目前的 Java 虚拟机只能实现 方法体的修改热部署,对于整个类的结构修改,仍然需要重启虚拟机,对类重新加载才能完成更新操作. 对于某些大型的应用来说,每次的重启都需要花费大量的时间成本.虽然 osgi 架构的出现,让模块重启 成为可能,但是如果模块之间有调用关系的话,这样的操作依然会让应用出现短暂的功能性休克.本文将 探索如何在不破坏 Java 虚拟机现有行为的前提下,实现某个单一类的热部署,让系统无需重启就完成某 个类的更新. 类

《Ext JS 4 First Look》翻译之一:新特性

第一章 新特性   Extjs 4相对于之前的版本作出了重大的修正.其中包括全新的类系统.新平台的引入.API的修整和加强还有新组件的引入(如新的图表和图形组件).Extjs 4提供更快速.更稳定的用户体验,并且让开发人员更容易上手. 在本章我们将学习到下列内容: 1.1. 入手Extjs 4 1.1.1. 包和命名空间的改进 1.1.2. API文档的使用(日后经常和它打交道) 1.2. Extjs新平台的架构 1.3.  Extjs 4的类系统 1.3.1. 类定义与对象实例化 1.3.2

意译:《JVM Internals》

译者语   为加深对JVM的了解和日后查阅时更方便,于是对原文进行翻译.内容是建立在我对JVM的认识的基础上翻译的,加上本人的英语水平有限,若有纰漏请大家指正,谢谢.   原文地址:http://blog.jamesdbloom.com/JVMInternals.html   一.前言   本文将介绍JVM内部架构.下图展示符合Java7规范的JVM内部主要组件.      下面我们将上述组件分为线程相关和线程独立两种类型来介绍. 二.目录 ThreadPer Threadprogram Cou

理解Android虚拟机体系结构

1. 什么是Dalvik虚拟机 Dalvik是Google公司自己设计用于Android平台的Java虚拟机,它是Android平台的重要组成部分,支持dex格式(Dalvik Executable)的Java应用程序的运行.dex格式是专门为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统.Google对其进行了特定的优化,使得Dalvik具有高效.简洁.节省资源的特点.从Android系统架构图知,Dalvik虚拟机运行在Android的运行时库层. 2. Dalvik虚拟机的

详解Android中实现热更新的原理_Android

这篇文章就来介绍一下Android中实现热更新的原理. 一.ClassLoader 我们知道Java在运行时加载对应的类是通过ClassLoader来实现的,ClassLoader本身是一个抽象来,Android中使用PathClassLoader类作为Android的默认的类加载器,PathClassLoader其实实现的就是简单的从文件系统中加载类文件.PathClassLoade本身继承自BaseDexClassLoader,BaseDexClassLoader重写了findClass方法

详解Android中实现热更新的原理

这篇文章就来介绍一下Android中实现热更新的原理. 一.ClassLoader 我们知道Java在运行时加载对应的类是通过ClassLoader来实现的,ClassLoader本身是一个抽象来,Android中使用PathClassLoader类作为Android的默认的类加载器,PathClassLoader其实实现的就是简单的从文件系统中加载类文件.PathClassLoade本身继承自BaseDexClassLoader,BaseDexClassLoader重写了findClass方法