Weird NoClassDefFoundError of Java class - java

Environment: jdk1.7
javax.servlet-api-3.0.1.jar is needed for this test.
Reproduce steps:
javac Test1.java -cp javax.servlet-api-3.0.1.jar build Test1.java with javax.servlet-api-3.0.1.jar
javac Test2.java -cp javax.servlet-api-3.0.1.jar build Test2.java with javax.servlet-api-3.0.1.jar
javac Test3.java build Test3.java
java -classpath .:javax.servlet-api-3.0.1.jar Test3 run Test3 with dependency. Following is the output. It's OK here.
hello world1
hello world2
But when this command java Test3 run, Exception is thrown. The result at the end of this post. The weird thing is that "hello world1" could be printed out, but instead of printing out "hello world2" an exception is thrown.
Test1.java
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
public class Test1 {
public void getRequest(HttpServletResponse resp) throws IOException {
OutputStream os = resp.getOutputStream();
resp.getOutputStream().close();
}
public void hello(String world) {
System.out.println("hello " + world);
}
}
Test2.java
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
public class Test2 {
public void getRequest(HttpServletResponse resp) throws IOException {
OutputStream os = resp.getOutputStream();
try {
resp.getOutputStream().close();
} catch (Exception e) {
}
}
public void hello(String world) {
System.out.println("hello " + world);
}
}
Test3.java
public class Test3 {
public static void main(String[] args) {
new Test1().hello("world1");
new Test2().hello("world2");
}
}
output of the final step. Test2.hello("world2") throw an exception:
hello world1
Exception in thread "main" java.lang.NoClassDefFoundError: javax/servlet/ServletOutputStream
at cn.test.abc1.Test3.main(Test3.java:9)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletOutputStream
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 6 more
I am very confused with the Exception. Because I didn't use any code in the Class ServletOutputStream. And the difference of the Test1 and Test2 is only a try blocked.
This Question is not a duplicated question as it marked. Because JVM should not throw an Exception when a try block get involved.

After compare the output of javap -v -c Test?, I get the answer.
The javac create StackMapTable attribute for try/catch block of Test2.java.
If StackMapTable is found on class loading, JVM will perform bytecode verification and check referenced class. That's why it throw java.lang.NoClassDefFoundError.
https://stackoverflow.com/a/25110513 describe more detail about StackMapTable.
Old wrong answer
I compile the Test1.java and decompile it, the source code become:
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletOutputStream;
public class Test1 {
public void getRequest(HttpServletResponse resp) throws IOException {
ServletOutputStream os = resp.getOutputStream();
resp.getOutputStream().close();
}
public void hello(String world) {
System.out.println("hello " + world);
}
}
Since the return object of resp.getOutputStream() is javax.servlet.ServletOutputStream. JVM still have to verify this class is sub-class of java.io.OutputStream before case it at runtime, so it try to load ServletOutputStream.class. But JVM cannot find it and throw ClassNotFoundException.

Makes perfect sense to me. Test3 references Test2 and Test1 and both need javax.servlet-api-3.0.1.jar on the classpath at runtime.

Related

“Exception in thread "main" java.lang.NoSuchMethodError: org.openqa.selenium.remote.HttpCommandExecutor.<init>(Ljava/util/Map;Ljava/net/URL;)V ”?

I am using Selenium.Winium tool for automation. I have included the below jar files for importing the selenium.winium packages
selenium-java.jar
winium-webdriver-0.1.0-1.jar
webdriver-selenium-0.9.7376.jar
selenium-server-standalone-3.14.0.jar
Below is my Java code :
import org.openqa.selenium.By;
import org.openqa.selenium.winium.DesktopOptions;
import org.openqa.selenium.winium.WiniumDriver;
import org.openqa.selenium.WebElement;
import java.net.MalformedURLException;
import java.net.URL;
public class WiniumTestProject
{
public static void main(String[] args) throws MalformedURLException, InterruptedException
{
DesktopOptions options= new DesktopOptions();
options.setApplicationPath("C:\\Windows\\System32\\calc.exe");
try
{
WiniumDriver driver=new WiniumDriver(new URL("http://localhost:9999"),options);
driver.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
Error Details :
When running the project through the command “java ProjectName” in Command window, it throws the following error.
Exception in thread "main" java.lang.NoSuchMethodError:
org.openqa.selenium.remote.HttpCommandExecutor.<init>(Ljava/util/Map;Ljava/net/URL;)V
at org.openqa.selenium.winium.WiniumDriverCommandExecutor.<init>(WiniumDriverCommandExecutor.java:64)
at org.openqa.selenium.winium.WiniumDriver.<init>(WiniumDriver.java:84)
at WiniumTestProject.main(WiniumTestProject.java:18)
Could anyone please help us to resolve this error?

Getting NullPointerException while running a normal Mapreduce program in Eclipse

I am getting NullPointerException when trying to execute a simple MapReduce program. I am unable to understand where the problem is?
package MapReduce.HadMapReduce;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class RecCount extends Configured implements Tool {
public int run(String[] arg0) throws Exception {
Job job = Job.getInstance(getConf());
FileInputFormat.setInputPaths(job, new Path("C:\\singledeck.txt"));
FileOutputFormat.setOutputPath(job, new Path("C:\\temp123"));
return job.waitForCompletion(true) ? 0 : 1;
}
public static void main(String args[]) throws Exception {
System.exit(ToolRunner.run(new RecCount(), args));
}
}
Error is:
Exception in thread "main" java.lang.NullPointerException
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1010)
at org.apache.hadoop.util.Shell.runCommand(Shell.java:483)
at org.apache.hadoop.util.Shell.run(Shell.java:456)
at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:722)
at org.apache.hadoop.util.Shell.execCommand(Shell.java:815)
at org.apache.hadoop.util.Shell.execCommand(Shell.java:798)
at org.apache.hadoop.fs.RawLocalFileSystem.setPermission(RawLocalFileSystem.java:731)
at org.apache.hadoop.fs.RawLocalFileSystem.mkOneDirWithMode(RawLocalFileSystem.java:489)
at org.apache.hadoop.fs.RawLocalFileSystem.mkdirsWithOptionalPermission(RawLocalFileSystem.java:530)
at org.apache.hadoop.fs.RawLocalFileSystem.mkdirs(RawLocalFileSystem.java:507)
at org.apache.hadoop.fs.FilterFileSystem.mkdirs(FilterFileSystem.java:305)
at org.apache.hadoop.mapreduce.JobSubmissionFiles.getStagingDir(JobSubmissionFiles.java:133)
at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:144)
at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1290)
at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1287)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
at org.apache.hadoop.mapreduce.Job.submit(Job.java:1287)
at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:1308)
at MapReduce.HadMapReduce.RecCount.run(RecCount.java:22)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:84)
at MapReduce.HadMapReduce.RecCount.main(RecCount.java:26)
This is the logic which is happening behind the scenes:
ToolRunner is calling the below run method and this method calls its other run method (which is pasted right below this) where the configuration is set if it is null.
public static int run(Tool tool, String[] args) throws Exception {
return run(tool.getConf(), tool, args);
}
public static int run(Configuration conf, Tool tool, String[] args) throws Exception {
if (conf == null) {
conf = new Configuration();
}
GenericOptionsParser parser = new GenericOptionsParser(conf, args);
// set the configuration back, so that Tool can configure itself
tool.setConf(conf);
// get the args w/o generic hadoop args
String[] toolArgs = parser.getRemainingArgs();
return tool.run(toolArgs);
}
In the last statement above run method is called which I implemented because I implemented Tool interface. I don't see any error in my code. Please let me know if you can find any!
Can someone please explain what is the problem with my code?

ClassCastException thrown when calling .asSubclass from separate jar

I have a program through which I have the following three classes. These first two are in jar1.jar:
Main (uses the jar loading trick found here):
package prob1;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class Main {
static List<Class<?>> classes = new ArrayList<Class<?>>();
static String pathToJar = "/Users/vtcakavsmoace/Desktop/jar2.jar";
public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
loadJar();
classes.get(0).asSubclass(A.class).newInstance().someMethod();
}
private static void loadJar() throws IOException, ClassNotFoundException {
JarFile jarFile = new JarFile(pathToJar);
Enumeration<JarEntry> e = jarFile.entries();
URL[] urls = { new URL("jar:file:" + pathToJar + "!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if (je.isDirectory() || !je.getName().endsWith(".class")) {
continue;
}
String className = je.getName().substring(0, je.getName().length() - 6);
className = className.replace('/', '.');
classes.add(cl.loadClass(className));
}
jarFile.close();
}
}
A:
package prob1;
public interface A {
void someMethod();
}
And a second class found in jar2.jar, B:
package prob2;
import prob1.A;
public class B implements A {
#Override
public void someMethod() {
System.out.println("Hello, world!");
}
}
As you can see, class B obviously implements interface A. However, when loading class B, and then attempting to call asSubclass on it, fails with the following exception:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.ClassCastException: class prob2.B
at java.lang.Class.asSubclass(Class.java:3404)
at prob1.Main.main(Main.java:20)
... 5 more
Note that this does not fail when run through Eclipse.
What am I doing wrong here? How can I fix this?
Okay, found the answer using the knowledge that Erwin Bolwidt gave me; in class Main, replacing:
URLClassLoader cl = URLClassLoader.newInstance(urls);
with:
URLClassLoader cl = URLClassLoader.newInstance(urls, Main.class.getClassLoader());
Fixes the problem. :P

JAVA rmi nested exception caused by class not found

I was learning rmi and I came up with a problem and I cannot solve it.
Here is the simple code
client code:
package rmi_test;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class client {
public static void main(String [] args) throws RemoteException, NotBoundException
{
Registry registry = LocateRegistry.getRegistry("127.0.0.1");
DNInterface s = (DNInterface) registry.lookup("DNInterface");
if (s.test())
System.out.println("Hello World");
}
}
Interface code:
package rmi_test;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface DNInterface extends Remote{
public boolean test() throws RemoteException;
}
Server Code:
package rmi_test;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class DataNodeImp implements DNInterface{
#Override
public boolean test() throws RemoteException {
System.out.println("test success");
return true;
}
public DataNodeImp()
{
super();
}
private static void boot() throws RemoteException
{
DNInterface d = new DataNodeImp();
DNInterface stub =
(DNInterface) UnicastRemoteObject.exportObject(d, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind("DNInterface", stub);
}
public static void main(String[] args) throws RemoteException
{
String name = "DNInterface";
boot();
}
}
Then I use the following commands to compile the code
javac -cp src: src/rmi_test/DNInterface.java
javac -cp src: src/rmi_test/DataNodeImp.java
javac -cp src: src/rmi_test/client.java
then i type
rmiregistry &
When I try to use
java -cp src: rmi_test.DataNodeImp to run the server
it said
Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: rmi_test.DNInterface
Is there anything wrong with the command I run the code?
Why I cannot find DNInterface.class?
Thank you very much!
The Registry doesn't have that class in its CLASSPATH.
The simplest solution is to use LocateRegistry.createRegistry() in the server JVM rather than rmiregistry.

Get HTML String From Webpage in Bukkit Plugin

I'm trying to create a plugin for minecraft bukkit servers. The goal is to read the string on the first line of an html page. If the result is True it will execute a command.
Here is the code I have right now:
import java.net.URLConnection;
import java.util.Scanner;
import java.util.logging.Logger;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public class main extends JavaPlugin{
public final Logger logger = Logger.getLogger("Minecraft");
public void onEnable(){
logger.info("[First] Has Been Enabled.");
}
public void onDisable(){
logger.info("[First] Has Been Disabled.");
}
public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {
Player player = (Player) sender;
if(commandLabel.equalsIgnoreCase("hello")){
player.sendMessage(ChatColor.GOLD + "Hello");
}
else if(commandLabel.equalsIgnoreCase("world")){
player.sendMessage(ChatColor.GOLD + "World");
}
else if(commandLabel.equalsIgnoreCase("coolman")){
player.setPlayerListName("coolman");
}
else if(commandLabel.equalsIgnoreCase("vote")){
String sourceLine = null;
// The URL address of the page to open.
URL address = new URL("http://www.koolflashgames.com/test.php");
// Open the address and create a BufferedReader with the source code.
InputStreamReader pageInput = new InputStreamReader(address.openStream());
BufferedReader source = new BufferedReader(pageInput);
// Append each new HTML line into one string. Add a tab character.
try {
sourceLine = source.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(sourceLine == "False"){
player.sendMessage("Thanks for voting!");
}
}
return false;
}
}
Creates the following error in the log:
2012-11-02 16:18:30 [SEVERE] null
org.bukkit.command.CommandException: Unhandled exception executing command 'vote' in plugin first v1.0
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46)
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:180)
at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:502)
at net.minecraft.server.NetServerHandler.handleCommand(NetServerHandler.java:915)
at net.minecraft.server.NetServerHandler.chat(NetServerHandler.java:828)
at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:810)
at net.minecraft.server.Packet3Chat.handle(Packet3Chat.java:44)
at net.minecraft.server.NetworkManager.b(NetworkManager.java:282)
at net.minecraft.server.NetServerHandler.d(NetServerHandler.java:111)
at net.minecraft.server.ServerConnection.b(SourceFile:35)
at net.minecraft.server.DedicatedServerConnection.b(SourceFile:30)
at net.minecraft.server.MinecraftServer.q(MinecraftServer.java:561)
at net.minecraft.server.DedicatedServer.q(DedicatedServer.java:213)
at net.minecraft.server.MinecraftServer.p(MinecraftServer.java:474)
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:406)
at net.minecraft.server.ThreadServerApplication.run(SourceFile:539)
Caused by: java.lang.NullPointerException
at java.io.Reader.<init>(Unknown Source)
at java.io.InputStreamReader.<init>(Unknown Source)
at me.storminmormon30.first.main.onCommand(main.java:43)
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
... 15 more
Looks like the error is somewhere else:
Unhandled exception executing command 'vote'
I don't see that command in the code snippet you have given
You should split each command into it's own class and register in in the plugin.yml, What I would do, is in the onEnable() method, set something like this:
getCommand("command").setExecutor(new CommandExecutor());
That will split off all of the commands into their own class, which would work better, and I would suggest it.
The issue with your code looks like a NPE in your class main on line 43 (its in your onEnable() method)

Categories

Resources