Re: Potential Software Failure

Markus Dahm <[email protected]>
Newsgroups gmane.comp.jakarta.bcel.devel
Message-ID <[email protected]>
Hi,

the program works fine for me (I slightly modified it to work
without JUnit). I dump the code to a file to see what's
generated and for the testCatch it looks like


public int runTest(int x)
Code(max_stack = 2, max_locals = 2, code_length = 11)
0:    aconst_null
1:    iconst_0
2:    invokevirtual     test.Catch.runTest (I)I (10)
5:    pop
6:    iconst_1
7:    ireturn
8:    pop
9:    iconst_1
10:   ireturn

Exception handler(s) =
 From    To      Handler Type
0       8       8       java.lang.NullPointerException(22)

BTW: I enhanced the code to use clazz.addEmptyConstructor(), but
that shouldn't make a difference.

When I run the program the output is

java CodeExceptionGenTest
true
NullPointerException thrown as expected
java.lang.NullPointerException
         at test.NoCatch.runTest(test/NoCatch.java)
         at CodeExceptionGenTest.testNoCatch(CodeExceptionGenTest.java:170)
         at CodeExceptionGenTest.main(CodeExceptionGenTest.java:145)

Cheers
	Markus

--
To unsubscribe, e-mail:   <mailto:[email protected]>
For additional commands, e-mail: <mailto:[email protected]>
TInterface.java (text/plain, 67 B)
public interface TInterface {
    public int runTest( int x );
}
CodeExceptionGenTest.java (text/plain, 4.7 KB)
import org.apache.bcel.Constants;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;

import java.security.SecureClassLoader;

public class CodeExceptionGenTest {
    public CodeExceptionGenTest( String name ) {
    }
    
    private static class MockClassLoader 
	extends SecureClassLoader
    {
	private CodeExceptionGenTest test = null;

	public MockClassLoader( CodeExceptionGenTest test ) {
	    super( TInterface.class.getClassLoader() ); 
	    this.test = test;
	}

	protected Class findClass( String className ) 
	    throws ClassNotFoundException
	{
	    ClassGen clazz = null;
	    if (className.equals( "test.NoCatch" )) {
		clazz = test.makeNoCatch();
	    }

	    if (className.equals( "test.Catch" )) {
		clazz = test.makeCatch();
	    }

	    if (clazz == null) {
		return super.findClass( className );
	    }
	    
	    JavaClass jClass = clazz.getJavaClass();

	    try {
	      jClass.dump(jClass.getClassName() + ".class");
	    } catch(Exception ex) {   }


	    byte bytecode[] = jClass.getBytes();
	    Class RC = defineClass( className,
				    bytecode, 0,
				    bytecode.length );
	    return RC;
	}
    }

    public ClassGen makeNoCatch() 
    {
	ClassGen clazz = new ClassGen("test.NoCatch",
				      "java.lang.Object",
				      "test/NoCatch.java",
				      Constants.ACC_PUBLIC,
				      new String[] 
	    { "TInterface" } );
	/*MethodGen constructor = 
	    makeConstructor( clazz );
	*/
	InstructionList instructions = new InstructionList();
	InstructionFactory factory = new InstructionFactory( clazz );

	instructions.append( factory.ACONST_NULL ); 
	instructions.append( factory.ICONST_0 );
	instructions.append( factory.createInvoke( "test.NoCatch",
						   "runTest",
						   Type.INT,
						   new Type[] { Type.INT },
						   Constants.INVOKEVIRTUAL));
	instructions.append( factory.POP );
	instructions.append( factory.ICONST_1 );
	instructions.append( factory.IRETURN );

	MethodGen runTest = 
	    new MethodGen( Constants.ACC_PUBLIC,
			   Type.INT,
			   new Type[] { Type.INT },
			   new String[] { "x" },
			   "runTest", "test.NoCatch",
			   instructions, clazz.getConstantPool() );

	runTest.setMaxStack();

	clazz.addMethod( runTest.getMethod() );
	clazz.addEmptyConstructor(Constants.ACC_PUBLIC);

	return clazz;
    }

    public ClassGen makeCatch() 
    {
	ClassGen clazz = new ClassGen("test.Catch",
				      "java.lang.Object",
				      "test/Catch.java",
				      Constants.ACC_PUBLIC,
				      new String[] 
	    { "TInterface" } );

	InstructionList instructions = new InstructionList();
	InstructionFactory factory = new InstructionFactory( clazz );

	instructions.append( factory.ACONST_NULL ); 
	instructions.append( factory.ICONST_0 );
	instructions.append( factory.createInvoke( "test.Catch",
						   "runTest",
						   Type.INT,
						   new Type[] { Type.INT },
						   Constants.INVOKEVIRTUAL));
	instructions.append( factory.POP );
	instructions.append( factory.ICONST_1 );
	instructions.append( factory.IRETURN );

	InstructionHandle beginTry = instructions.getStart();
	InstructionHandle endTry = instructions.getEnd();
	InstructionHandle catchHandle =
	    instructions.append( factory.POP );
	instructions.append( factory.ICONST_1 );
	instructions.append( factory.IRETURN );

	MethodGen runTest = 
	    new MethodGen( Constants.ACC_PUBLIC,
			   Type.INT,
			   new Type[] { Type.INT },
			   new String[] { "x" },
			   "runTest", "test.Catch",
			   instructions, clazz.getConstantPool() );
	ObjectType npe = new ObjectType( "java.lang.NullPointerException" );
	runTest.addExceptionHandler( beginTry, endTry, catchHandle, npe );

	runTest.setMaxStack();

	clazz.addEmptyConstructor(Constants.ACC_PUBLIC);
	clazz.addMethod( runTest.getMethod() );
	
	return clazz;
    }

    public static void main(String[] args)
	throws Throwable
    {
      testCatch();
      testNoCatch();
    }

  public static void testCatch() throws Throwable {
      CodeExceptionGenTest test = new CodeExceptionGenTest("foo");
      MockClassLoader loader = new MockClassLoader(test);

      Class clazz = loader.loadClass("test.Catch");
      TInterface object = 
	(TInterface) clazz.newInstance();
      
      System.out.println(object.runTest( 3 ) == 1);
    }

    public static void testNoCatch()
	throws Throwable
    {
      CodeExceptionGenTest test = new CodeExceptionGenTest("foo");
      MockClassLoader loader = new MockClassLoader(test);

	Class clazz = loader.loadClass("test.NoCatch");
	TInterface object = 
	    (TInterface) clazz.newInstance();
	
	try {
	    object.runTest( 5 );
	    System.out.println("Expected NullPointerException to be thrown.");
	} catch (NullPointerException npe) {
	  System.out.println("NullPointerException thrown as expected");
	  npe.printStackTrace();
	}
    }
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.