跳至主要内容

Class Not Found vs No Class Def Found

Class Not Found vs No Class Def Found

When we are working on JavaEE, we will always has multiple issues related to classes and ClassLoader.
We may struggle to find some strange memory leaks caused by ClassLoader; we may fail to run some applications because it fail to find some class; we may encounter cases when multiple versions of library conflict.
In order to solve all similar problems one for all, today we focus the understanding of two exception (to be precise, one exception and one error):

  • java.lang.ClassNotFoundException
  • java.lang.NoClassDefFoundError

ClassLoader

Before we get to solve the problem, we have to skim some basic knowledge of class loading.

In the world of Java, almost all things are abstracted into a class. Class is also a class, which organized by classpath and package structure. In order to load classes when suitable, JVM use the abstraction of ClassLoader to locate or generate data that constitutes a definition for the class.
The class loader use the a model called delegation, in which a class loader will delegate the search for class/resources to its parent before attempting to find them by itself. The most basic class, like class under java.* are all loaded by bootstrap class loader, which can’t be written in Java (or who will load this class?) and is the ancestor of all other class loaders. Other common class loaders are extension class loader and system class loader.

Class Not Found

From the doc of this ClassNotFoundException:

Thrown when an application tries to load in a class through its string name using:

  • The forName method in class Class.
  • The findSystemClass method in class ClassLoader .
  • The loadClass method in class ClassLoader.

but no definition for the class with the specified name could be found.

This doc sum up the three way to load a class in JVM, but it doesn’t tell us what does it mean and when it will be thrown.

The common way for class loader to work is to read a “class file” from directory specified by classpath, so this means that exception indicates the class was not found on the classpath. This indicates that we were trying to load the class definition, and the class did not exist on the classpath.

So, when this exception occurs, it may be means:

  • we have wrong class path specified;
  • we forget the full package name, which is required for class loader object to search in right directory;
  • we don’t have the permission on some directory or file

No Class Def Found

From NoClassDefFoundError:

Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.

The docs points out the core of this error: this code can compile, but fail to run. It can have following possible reasons:

  • the lib required is provided in compile classpath, but not provided in runtime environment – this error should be caused by a ClassNotFoundException:
    • lib is not packaged into Jar/War
    • wrong class path settings in IDE and/or wrong class path environment variable
    • access class across different class loaders
  • this error is a subclass of LinkageError, so it will throw when:
    • when init class, i.e. init static variable or execute static code block and meet some errors with ExceptionInInitializerError
    • other verification error of class: illegal name, class file not match its binary name etc.

Ref

Written with StackEdit.

评论

此博客中的热门博文

Spring Boot: Customize Environment

Spring Boot: Customize Environment Environment variable is a very commonly used feature in daily programming: used in init script used in startup configuration used by logging etc In Spring Boot, all environment variables are a part of properties in Spring context and managed by Environment abstraction. Because Spring Boot can handle the parse of configuration files, when we want to implement a project which uses yml file as a separate config file, we choose the Spring Boot. The following is the problems we met when we implementing the parse of yml file and it is recorded for future reader. Bind to Class Property values can be injected directly into your beans using the @Value annotation, accessed via Spring’s Environment abstraction or bound to structured objects via @ConfigurationProperties. As the document says, there exists three ways to access properties in *.properties or *.yml : @Value : access single value Environment : can access multi

Elasticsearch: Join and SubQuery

Elasticsearch: Join and SubQuery Tony was bothered by the recent change of search engine requirement: they want the functionality of SQL-like join in Elasticsearch! “They are crazy! How can they think like that. Didn’t they understand that Elasticsearch is kind-of NoSQL 1 in which every index should be independent and self-contained? In this way, every index can work independently and scale as they like without considering other indexes, so the performance can boost. Following this design principle, Elasticsearch has little related supports.” Tony thought, after listening their requirements. Leader notice tony’s unwillingness and said, “Maybe it is hard to do, but the requirement is reasonable. We need to search person by his friends, didn’t we? What’s more, the harder to implement, the more you can learn from it, right?” Tony thought leader’s word does make sense so he set out to do the related implementations Application-Side Join “The first implementation

Implement isdigit

It is seems very easy to implement c library function isdigit , but for a library code, performance is very important. So we will try to implement it and make it faster. Function So, first we make it right. int isdigit ( char c) { return c >= '0' && c <= '9' ; } Improvements One – Macro When it comes to performance for c code, macro can always be tried. #define isdigit (c) c >= '0' && c <= '9' Two – Table Upper version use two comparison and one logical operation, but we can do better with more space: # define isdigit(c) table[c] This works and faster, but somewhat wasteful. We need only one bit to represent true or false, but we use a int. So what to do? There are many similar functions like isalpha(), isupper ... in c header file, so we can combine them into one int and get result by table[c]&SOME_BIT , which is what source do. Source code of ctype.h : # define _ISbit(bit) (1 << (