JJJVMInterpreter implements JJJVMConstants { public static Object invoke(final JJJVMClass caller, final JJJVMObject instance, final JJJVMMethod methodToInvoke, final Object[] args, final Object[] stack, final Object[] vars) throws Throwable { final int methodFlags = methodToInvoke.getFlags(); if ((methodFlags & ACC_NATIVE) != 0) { throw new IllegalArgumentException("Method must not be native [" + methodToInvoke + ']'); } if ((methodFlags & ACC_SYNCHRONIZED) != 0) { final Object syncObject; if ((methodFlags & ACC_STATIC) != 0) { syncObject = caller; } else { syncObject = instance; } synchronized (syncObject) { return _invoke(caller, instance, methodToInvoke, args, 0, stack, vars); } } else { return _invoke(caller, instance, methodToInvoke, args, 0, stack, vars); } }  static Object invoke(final JJJVMClass caller, final JJJVMObject instance, final JJJVMMethod methodToInvoke, final Object[] args, final Object[] stack, final Object[] vars);  }
@Test @Ignore("ignored because JvaSE wrapper doesn't support instantiation of abstract classes and java.lang.Enum is abstract one") public void testIntegration_TestEnumeration() throws Throwable { final JJJVMProvider provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestEnumeration"); final JJJVMObject obj = testKlazz.newInstance(true); final JJJVMMethod disabledMethod = testKlazz.findMethod("testDISABLED", "()Ljava/lang/String;"); final JJJVMMethod enabledMethod = testKlazz.findMethod("testENABLED", "()Ljava/lang/String;"); assertEquals("N",disabledMethod.invoke(obj, new Object[0])); assertEquals("Y",enabledMethod.invoke(obj, new Object[0])); }
@Test public void testIntegration_TestThrow() throws Throwable { final JJJVMProvider provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestThrow"); final JJJVMObject obj = testKlazz.newInstance(true); final JJJVMMethod throwIOE = testKlazz.findMethod("throwIOE", "()V"); final JJJVMMethod throwDIFF = testKlazz.findMethod("throwDIFF", "(I)V"); try { throwIOE.invoke(obj, null); fail("Must throw IOE"); } catch (IOException ex) { assertEquals("IOE", ex.getMessage()); assertEquals(8, ex.getStackTrace()[0].getLineNumber()); } try { throwDIFF.invoke(obj, new Object[]{0}); fail("Must throw AE"); } catch (ArithmeticException ex) { assertEquals("arith", ex.getMessage()); assertEquals(15, ex.getStackTrace()[0].getLineNumber()); } try { throwDIFF.invoke(obj, new Object[]{1}); fail("Must throw UOE"); } catch (UnsupportedOperationException ex) { assertEquals("uns", ex.getMessage()); assertEquals(17, ex.getStackTrace()[0].getLineNumber()); } try { throwDIFF.invoke(obj, new Object[]{9993}); fail("Must throw ISE"); } catch (IllegalStateException ex) { assertEquals("ise", ex.getMessage()); assertEquals(23, ex.getStackTrace()[0].getLineNumber()); assertEquals("npe", ex.getCause().getMessage()); } }
@Test public void testIntegration_TestClassInheritance() throws Throwable { final JJJVMProvider provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestClassInheritance$Klazz3"); final JJJVMObject obj = testKlazz.newInstance(true); obj.setFieldValue("field1", 123, true); obj.setFieldValue("field2", 345, true); obj.setFieldValue("field3", 678, true); assertEquals(123.456d, ((Double) testKlazz.readStaticField("dblStatField")), 0.0d); assertEquals(Integer.valueOf(123), obj.getFieldValue("field1", true)); assertEquals(Integer.valueOf(345), obj.getFieldValue("field2", true)); assertEquals(Integer.valueOf(678), obj.getFieldValue("field3", true)); assertEquals((123 * 999) / 345 + 678, testKlazz.findMethod("calc", "(I)I").invoke(obj, new Object[]{999})); }
@Test public void testSynchronization_staticMethods() throws Throwable { final AtomicLong callCounter = new AtomicLong(); final JJJVMProvider provider = new JSEProviderImpl(this) { final AtomicInteger counter = new AtomicInteger(); @Override public Object invoke(JJJVMClass caller, Object instance, String jvmFormattedClassName, String methodName, String methodSignature, Object[] arguments) throws Throwable { if (jvmFormattedClassName.equals("java/io/PrintStream") && methodName.equals("println") && methodSignature.equals("(I)V")) { synchronized (counter) { callCounter.incrementAndGet(); final int value = (Integer) arguments[0]; if (counter.get() == 0) { counter.set(value == 1 ? 1 + 2 + 3 + 4 + 5 : 6 + 7 + 8 + 9 + 10); counter.addAndGet(-value); } else { assertTrue("Counter must be every time zero or greater", counter.addAndGet(-value) >= 0); } } return null; } return super.invoke(caller, instance, jvmFormattedClassName, methodName, methodSignature, arguments); } }; final JJJVMClass klazz = loadClassFromClassPath(provider, "com.igormaznitsa.jjjvm.testclasses.TestSynchronization"); final JJJVMMethod smethod1 = klazz.findMethod("smethod1", "()V"); final JJJVMMethod smethod2 = klazz.findMethod("smethod2", "()V"); assertNotNull(smethod1); assertNotNull(smethod2); final JJJVMObject obj = klazz.newInstance(true); final int NUM = 100000; final Thread thr1 = new Thread(new Runnable() { public void run() { try { Thread.sleep(200L); for (int i = 0; i < NUM; i++) { smethod1.invoke(null, null); } } catch (Throwable ex) { ex.printStackTrace(); fail("Error in thread 1"); } } }); final Thread thr2 = new Thread(new Runnable() { public void run() { try { Thread.sleep(200L); for (int i = 0; i < NUM; i++) { smethod2.invoke(null, null); } } catch (Throwable ex) { ex.printStackTrace(); fail("Error in thread 2"); } } }); thr1.start(); thr2.start(); thr1.join(); thr2.join(); assertTrue(callCounter.get() != 0); }
@Test public void testSynchronization_nonstaticMethods() throws Throwable { final AtomicLong callCounter = new AtomicLong(); final JJJVMProvider provider = new JSEProviderImpl(this) { final AtomicInteger counter = new AtomicInteger(); @Override public Object invoke(JJJVMClass caller, Object instance, String jvmFormattedClassName, String methodName, String methodSignature, Object[] arguments) throws Throwable { if (jvmFormattedClassName.equals("java/io/PrintStream") && methodName.equals("println") && methodSignature.equals("(I)V")) { synchronized (counter) { callCounter.incrementAndGet(); final int value = (Integer) arguments[0]; if (counter.get() == 0) { counter.set(value == 1 ? 1 + 2 + 3 + 4 + 5 : 6 + 7 + 8 + 9 + 10); counter.addAndGet(-value); } else { assertTrue("Counter must be every time zero or greater", counter.addAndGet(-value) >= 0); } } return null; } return super.invoke(caller, instance, jvmFormattedClassName, methodName, methodSignature, arguments); } }; final JJJVMClass klazz = loadClassFromClassPath(provider, "com.igormaznitsa.jjjvm.testclasses.TestSynchronization"); final JJJVMMethod smethod1 = klazz.findMethod("method1", "()V"); final JJJVMMethod smethod2 = klazz.findMethod("method2", "()V"); assertNotNull(smethod1); assertNotNull(smethod2); final JJJVMObject obj = klazz.newInstance(true); final int NUM = 100000; final Thread thr1 = new Thread(new Runnable() { public void run() { try { Thread.sleep(200L); for (int i = 0; i < NUM; i++) { smethod1.invoke(obj, null); } } catch (Throwable ex) { ex.printStackTrace(); fail("Error in thread 1"); } } }); final Thread thr2 = new Thread(new Runnable() { public void run() { try { Thread.sleep(200L); for (int i = 0; i < NUM; i++) { smethod2.invoke(obj, null); } } catch (Throwable ex) { ex.printStackTrace(); fail("Error in thread 2"); } } }); thr1.start(); thr2.start(); thr1.join(); thr2.join(); assertTrue(callCounter.get() != 0); }
@Test public void testIntegration_TestTableswitch() throws Throwable { final JSEProviderImpl provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestTableswitch"); assertTrue(JSEProviderImpl.tryCastTo(testKlazz, "java/lang/Object")); assertFalse(JSEProviderImpl.tryCastTo(testKlazz, "java/util/Map")); assertTrue(JSEProviderImpl.tryCastTo(testKlazz, "java/io/Serializable")); assertEquals(Integer.valueOf(1234), testKlazz.findField("sfield1").getStaticValue()); assertEquals(Long.valueOf(56787L), testKlazz.findField("sfield2").getStaticValue()); assertEquals("Hello world", testKlazz.findField("sfield3").getStaticValue()); final Double arg = new Double(11233.0932d); final JJJVMObject obj = testKlazz.newInstance("(D)V", new Object[]{arg}, null, null); assertNotNull(obj); assertSame(testKlazz, obj.getDeclaringClass()); assertSame(arg, testKlazz.findField("field4").get(obj)); assertEquals(Integer.valueOf(9876), testKlazz.findField("field1").get(obj)); assertEquals(Long.valueOf(6666L), testKlazz.findField("field2").get(obj)); assertEquals("Ugums", testKlazz.findField("field3").get(obj)); final JJJVMMethod doCalcMethod = testKlazz.findMethod("doCalc", "(D)D"); assertEquals(new Double(11233.0932d + -652374.23d / 34 - (23 * -652374.23d)), doCalcMethod.invoke(obj, new Object[]{new Double(-652374.23d)})); final JJJVMMethod doTableSwitchMethod = testKlazz.findMethod("doTableSwitch", "(J)D"); assertEquals(new Double(1.0d), doTableSwitchMethod.invoke(obj, new Object[]{-1L})); assertEquals(new Double(1.3d), doTableSwitchMethod.invoke(obj, new Object[]{0L})); assertEquals(new Double(2.0d), doTableSwitchMethod.invoke(obj, new Object[]{1L})); assertEquals(new Double(8.0d), doTableSwitchMethod.invoke(obj, new Object[]{2L})); assertEquals(new Double(81.0d), doTableSwitchMethod.invoke(obj, new Object[]{9L})); assertEquals(new Double(93 * 93), doTableSwitchMethod.invoke(obj, new Object[]{93L})); }
@Test public void testIntegration_TestIssue_appendChars1() throws Throwable { final JSEProviderImpl provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestIssue"); final JJJVMMethod append = testKlazz.findMethod("trampoline", "()Ljava/lang/String;"); String res = (String) append.invoke(null, new Object[]{}); String expected = new StringBuilder().append((char) ('a' ^ 'b')).toString(); assertEquals(expected, res); }
@Test public void testIntegration_TestIssue_appendChars2() throws Throwable { final JSEProviderImpl provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestIssue"); final JJJVMMethod append = testKlazz.findMethod("appendChars", "(CC)Ljava/lang/String;"); String res = (String) append.invoke(null, new Object[]{'a', 'b'}); String expected = new StringBuilder().append((char) ('a' ^ 'b')).toString(); assertEquals(expected, res); }
@Test public void testIntegration_TestIssue_appendInts() throws Throwable { final JSEProviderImpl provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestIssue"); final JJJVMMethod append = testKlazz.findMethod("appendInts", "(II)Ljava/lang/String;"); String res = (String) append.invoke(null, new Object[]{0x61, 0x62}); String expected = new StringBuilder().append((char) ('a' ^ 'b')).toString(); assertEquals(expected, res); }
@Test public void testIntegration_TestIssue_BooleanObjectAllocation() throws Throwable { final JSEProviderImpl provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestIssue"); final JJJVMMethod append = testKlazz.findMethod("allocateBooleans", "()[Ljava/lang/Object;"); Object[] res = (Object[]) append.invoke(null, null); assertEquals(Boolean.TRUE, res[0]); assertEquals(Boolean.FALSE, res[1]); assertEquals(Boolean.TRUE, res[2]); }
@Test public void testIntegration_TestInvoke() throws Throwable { final JJJVMProvider provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestInvoke"); final JJJVMObject obj = testKlazz.newInstance(true); final JJJVMMethod calc = testKlazz.findMethod("calc", "(I)I"); final JJJVMMethod calcLong = testKlazz.findMethod("calc", "(J)J"); assertEquals((125 * 125) / 2 + 10, calc.invoke(obj, new Object[]{new Integer(125)})); assertEquals((125L * 125L) / 2L + 10L, calcLong.invoke(obj, new Object[]{new Long(125L)})); }
@Test public void testIntegration_TestVector() throws Throwable { final JJJVMProvider provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestVector"); final JJJVMObject obj = testKlazz.newInstance(true); final JJJVMMethod fillVector = testKlazz.findMethod("fillVector", "(Ljava/util/Vector;)Ljava/util/Vector;"); final JJJVMMethod makeVector = testKlazz.findMethod("makeVector", "()Ljava/util/Vector;"); final Vector theVector = new Vector(); theVector.add("1"); theVector.add("2"); theVector.add("3"); final Vector result = (Vector) fillVector.invoke(obj, new Object[]{theVector}); assertSame(theVector, result); assertArrayEquals(new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, result.toArray()); assertArrayEquals(new Object[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, ((Vector) makeVector.invoke(obj, null)).toArray()); }
@Test public void testIntegration_TestIterable() throws Throwable { final JJJVMProvider provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestIterable"); final JJJVMObject obj = testKlazz.newInstance(true); final JJJVMMethod iterableMethod = testKlazz.findMethod("iterate", "(Ljava/util/List;)I"); assertEquals(0,iterableMethod.invoke(obj, new Object[]{Collections.EMPTY_LIST})); List list = new ArrayList(); list.add(1); assertEquals(1,iterableMethod.invoke(obj, new Object[]{list})); list.add(2); assertEquals(2,iterableMethod.invoke(obj, new Object[]{list})); list.clear(); assertEquals(0,iterableMethod.invoke(obj, new Object[]{list})); }
@Test public void testIntegration_TestInnerClasses() throws Throwable { final JJJVMProvider provider = new JSEProviderImpl(this); final JJJVMClass testKlazz = loadClassFromClassPath(provider, "com/igormaznitsa/jjjvm/testclasses/TestInnerClasses"); assertEquals(0, JJJVMClassImpl.getNumberOfLoadingClasses()); assertEquals("TestInnerClasses.java", testKlazz.getSourceFileName()); final JJJVMObject instance = testKlazz.newInstance(true); final JJJVMMethod test = testKlazz.findMethod("test", "(II)I"); assertEquals(96, test.invoke(instance, new Object[]{123, 456})); }