Cross Column

Showing posts with label Class Loader. Show all posts
Showing posts with label Class Loader. Show all posts

Monday, March 3, 2014

java.lang.UnsatisfiedLinkError: Setting Environment Variable

This UnsatisfiedLinkError Error is thrown to indicate that an appropriate native language definition of a method declared native cannot be found by the Java Virtual Machine.
java.lang.UnsatisfiedLinkError: Can't load library: ...libmawt.so[1]
When a Java application loads a native library using the System.loadLibrary() method, the java.library.path is scanned for the specified library. If the JVM is not able to detect the requested library, it throws an UnsatisfiedLinkError.[15]

In this article, we will look at setting environment variables to revolve this kind of errors assuming missing libraries are installed correctly and have appropriate permissions and ownership.

Tell Whom Where to Find What


Different environment variables differ in the following aspects:
  • Tell whom where to find what
Here, we have summarized environment variables based on the above criteria:

Environment Variable WhomWhatDescription
PATH
Windows/bin When a command is entered in a command shell or a system call is made by a program to execute a program, the system first searches the current working directory and then searches the path, examining each directory from left to right, looking for an executable filename (EXE, COM, BAT, or CMD) that matches the command name given.
/libSet the shared library path environment variable.
PATH
Linux/binTells the shell which directories to search for executable files in response to commands issued by a user.[2]
LIBPATH AIX /lib Set the shared library path environment variable.[16]
LD_LIBRARY_PATH
Linux
Unix
Solaris
/lib
  • In Unix, the environment variable LD_LIBRARY_PATH or its variants (see next section) is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories
  • LD_LIBRARY_PATH is handy for development and testing
JAVA_HOME
WebLogic,[9] IDEs,[8Other ProgramsJRE (Java runtime environment)
  • Note that java.home is always there inside JVM, whereas JAVA_HOME exists mainly in your shell environment and you may pass it to JVM as a system property.[4]
  • You can use it to set the PATH variable. This is very convenient, because if you install another version of the JDK, all you need to do is to update your JAVA_HOME, without having to touch the PATH.[14]
  • If the application server ships with a JVM, then the JAVA_HOME environment variable must be set to reference it.
classpath or CLASSPATHJava Launcher or Java CompilerUser-defined classes and packages[10]
  • Classpath in Java is path to directory or list of directory which is used by ClassLoaders[11,20] to find and load class in Java program
  • By default only the packages of the JDK standard API and extension packages are accessible without needing to set where to find them.[7]
  • The path for all user-defined packages and libraries must be set in the command-line (or in the Manifest associated with the Jar file containing the classes).
  • Instead of setting the  classpath on the command lines, the environment variable named CLASSPATH may be used.

Here are the summarized system properties used during class loading based on the above criteria:


System PropertyWhomWhatDescription
java.library.path
JVMnative librariesThe Java Virtual Machine (JVM) uses the java.library.path property in order to locate native libraries. This property is part of the system environment used by Java, in order to locate and load native libraries used by an application.  Note that java.library.path is linked to LIBPATH or PATH or LD_LIBRARY_PATH, depending on the OS.
sun.boot.library.path
JVMnative librariesThe Java Virtual Machine (JVM) uses the sun.boot.library.path property in order to locate native libraries. This property is part of the system environment used by Java, in order to locate and load native libraries used by an application.  Note that sun.boot.library.path is searched before java.library.path.

Conclusions


If you have set your shared-library-path environment variable[3,4,5]  and system properties[15] correctly, you should be able to resolve this error. Read [1,15] for more information.
java.lang.UnsatisfiedLinkError: Can't load library: ...libmawt.so[1]

When you set environment variables, you want to consider which user(s) you want to set them for. For example, you can set environment variables for either your user only, or for all users (System variables). If you run Java applications in a WebLogic server, oftentimes you set environment variables such as LD_LIBRARY_PATH, etc. in the setDomainEnv.cmd/sh script (see also setWLSEnv.cmd/sh script) of a WebLogic domain.[6] In this way, you can avoid setting environment variables in the global scope, which may affect other applications.

As you may have noticed, there are idiosyncrasies of environment variables among platforms. For example, to set the shared-library-path environment variable, you do this differently on different platforms:


Operation System
Environment Variable
Windows
PATH
AIX
LIBPATH
Solaris and Linux
LD_LIBRARY_PATH
HP-UX
SHLIB_PATH


References

  1. Can't load library libmawt.so
  2. PATH Definition
  3. Purpose of JAVA_HOME and PATH environment variables ?
  4. Why do you need JAVA_HOME environment variable?
    • To ensure that your Java programs pick the right Java.exe
    • To specify which installed versions of Java as default
    • To use tools/libraries only available in JDK
  5. Shared Libraries
  6. weblogic.Server Command-Line Reference
  7. classpath (Java)
  8. Configuring JDeveloper with a Different JDK (Xml and More)
  9. Configuring WebLogic Server with a Different JVM (Xml and More)
  10. Java Throwable: ClassNotFoundException vs. NoClassDefFoundError (Xml and More)
  11. WebLogic's Classloading Framework (Xml and More)
  12. Using the Classloader Analysis Tool (CAT)
  13. WebLogic Server (WLS) Support Pattern: Investigating Different Classloading Issues (Doc ID 1572862.1)
  14. Installing the JDK Software and Setting JAVA_HOME
  15. java.library.path – What is it and how to use 
  16. LIBPATH: Setting library search paths 
  17. Setting up the ODWEK application development environment
  18. java classpath separator  
    • In Unix/Linux/Solaris
      • CLASSPATH are separated by colons(:)
    • In Windows
      • CLASSPATH are separated by semicolons(;) 
  19. If the message says "java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path". The "lwjgl" is interpreted in a platform-dependent way:
    • On Windows
      • it means LWJGL.DLL . 
    • On Linux and many other UNIX variants
      • it means "liblwjgl.so"
      • On other platforms
        • it may mean something else
  20. Error: Could not find or load main class weblogic.Server
    • Check your classpath or CLASSPATH
  21. Java Evolution: JDK and JRE File Structure (Xml and More)

Thursday, November 7, 2013

Java Throwable: ClassNotFoundException vs. NoClassDefFoundError

Many times we have confused ourselves with the following two Java Throwable messages:

Although both of them are related to Java Classpath,[7] they are different.[1] In a nutshell, they differ in this way:
  • ClassNotFoundException
    • Thrown when an application tries to load a class at run-time and name was provided during runtime not at compile time
  • NoClassDefFoundError[11,12]
    • When JVM or a ClassLoader instance is not able to find a particular class at runtime which was available during compile time

ClassNotFoundException


ClassNotFoundException is 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. See How-To section below for solutions.

NoClassDefFoundError


The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found. One way to debug NoClassDefFoundError is going back to the design-time environment. Using an IDE, you might be able to find where the class is coming from at compile time. Then use that as a clue to find why that class cannot be found at runtime. See How-To section for more details.

What Could Go Wrong?


Classpath[7] in Java is path to directory or list of directory which is used by ClassLoaders[3] to find and load class in Java program. If a class cannot be found at runtime, it may be due to:
  • Classloaders are not set up correctly[3]
  • Class is corrupted
    • Java compiler is not backwards compatible. For example, bytecode generated with JDK 7 won't run in Java 1.6 JVM.[2]
  • Jar file could be renamed in the runtime environment
  • Your startup script may have overridden Classpath environment variable
  • You might be running your program using jar command and class was not defined in manifest file's ClassPath attribute.

How to Resolve it?


The application that triggered the request to load a class receives a ClassNotFoundException or NoClassDefFoundError if neither the classloader nor any of its ancestors can locate the class.[3] In that case, you can take the following actions:
  • You can use System.getproperty("java.class.path") to get the class path used by your Java application at runtime.[4]
  • Try to run with -classpath option using the classpath you think would work: if it works, then it's a sign that some one is overriding java classpath.
  • Check the permission of your jar files.  Your application may not be able to access them.
  • Enable class loading traces at JVM level. For example, you can specify -verbose:class for both JRockit and HotSpot.[5]
  • If your application is deployed in WebLogic server, read [3] and enable classloader debugging. 
    •  For example, you may want to set:
      • -Dweblogic.utils.classloaders.GenericClassLoader.Verbose=true 
      • -Dweblogic.utils.classloaders.ChangeAwareClassLoader.Verbose=true
    • You can also use Classloader Analysis Tool (http://localhost:port/wls-cat/) which is deployed by default on admin servers of domains in development mode.[6]
    • If your application runs in one environment and not in another,
      • Try adding the CLASSPATH explicitly pointing to your jars in setDomainEnv script 
      • You can also set "EXT_PRE_CLASSPATH=...." or "EXT_POST_CLASSPATH=..." where "..." are your jar files. The setDomainEnv.sh will pick up these and add to CLASSPATH. The above environment variables can be set when you log on or somewhere at the top of setDomainEnv.sh.



References

  1. 3 ways to solve java.lang.NoClassDefFoundError in Java J2EE
  2. Is JDK “upward” or “backward” compatible?
  3. WebLogic's Classloading Framework (Xml and More)
  4. System Properties
  5. -verbose:class Option
  6. Using the new WebLogic Classloader Analysis Tool (CAT)
    • Note that I'm not sure if this is still available in newer WLS releases.
  7. How to Set Classpath for Java on Windows Unix and Linux
    • Main difference between PATH and CLASSPATH is that former is used to locate Java commands while later is used to locate Java class files.
  8. java.lang.UnsatisfiedLinkError: Setting Environment Variable (Xml and More)
  9. Using the Classloader Analysis Tool (CAT)
  10. WebLogic Server (WLS) Support Pattern: Investigating Different Classloading Issues (Doc ID 1572862.1)
  11. If you use JPA 2.1 with WLS 12.1.1 or 12.1.2, then you may see this (because JPA 2.1 only supported starting in 12.1.3):
    • java.lang.NoClassDefFoundError: javax/persistence/StoredProcedureQuery
  12. java.lang.NoClassDefFoundError: sun/io/CharacterEncoding (Xml and More)


Tuesday, April 2, 2013

java.lang.UnsupportedClassVersionError

When running an application named StoreFrontService, we have run into this exception:
  • java.lang.UnsupportedClassVersionError
In this article, we will examine what it is and how to resolve it.

Class Loading Phases


There are three phases in class loading[1]:
  • Loading
    • See below
  • Linking
    • Bytecode verification[6]
      • Checks the classfile semantics, checks the constant pool symbols, and does type checking
    • Preparation
      • Creates and initializes static fields to standard defaults and allocates method tables
  • Initializing
    •  Runs the class static initializers, and initializers for static fields
For a given Java class or Java interface, the load class phase takes its name, finds the binary in Java classfile format, defines the Java class, and creates a java.lang.Class object to represent that given Java class or Java interface.
The load class phase can throw a NoClassDefFound error if a binary representation of a Java class or Java interface cannot be found. In addition, the load class phase does format checking on the syntax of the classfile, which can throw a ClassFormatError or UnsupportedClassVersionError.

The Exception


In our expriement, we have seen the following exception being thrown:

####<Mar 21, 2013 8:16:43 AM PDT> <Error> <Class Loaders> <sfperf-x6250-10> <MS_1> <[ACTIVE] ExecuteThread: '8' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1363879003661> <BEA-2162500> <Class, oracle.fodemo.storefront.store.service.server.serviceinterface.StoreFrontServiceImpl, was compiled with an incompatible version of Java. Make sure that all the classes needed by the application have been compiled with a compatible java version. java.lang.UnsupportedClassVersionError: oracle/fodemo/storefront/store/service/server/serviceinterface/StoreFrontServiceImpl : unsupported classversion 51.0
java.lang.UnsupportedClassVersionError: oracle/fodemo/storefront/store/service/server/serviceinterface/StoreFrontServiceImpl : unsupported classversion 51.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14

      
This turns out to be that our application StoreFrontService was compiled in JDK 7 (class version: 51)[7] and we were running it on JRockit bundled with Java 1.6 VM (class version: 50). The compiler is not backwards compatible[2] because bytecode generated with JDK 7 won't run in Java 1.6 VM (unless compiled with the -target 1.6 flag[3]). But the JVM is backwards compatible, as it can run older bytecodes.

References

  1. Java Performance by Charlie Hunt, Binu John, David Dagastine 
  2. Is JDK “upward” or “backward” compatible?
  3. Cross-Compilation Options
  4. Java SE 6 vs. JRE 1.6 vs. JDK 1.6 - What do these mean?
  5. JRockit Version Information
  6. Java Virtual Machine Specification
  7. Unsupported major.minor version 51.0

© Travel for Life Guide. All Rights Reserved.

Analytical Insights on Health, Culture, and Security.