JDK-4948598 : Unusable array parameter and return types for Active-X bridge
  • Type: Bug
  • Component: deploy
  • Sub-Component: plugin
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2003-11-04
  • Updated: 2003-11-07
  • Resolved: 2003-11-07
Related Reports
Duplicate :  
Description
				report += "object array content value not identical: " + object1 + " - " + object2 + "\r\n";
			}
			if (object1.equals(object2))
			{
				report += "object array content value equal: " + object1 + " - " + object2 + "\r\n";
			}
			else
			{
				report += "object array content value not equal: " + object1 + " - " + object2 + "\r\n";
			}
		}
*/
		
		return report;
	}

	/**
	 * @return
	 */
	public boolean[] getBooleanArrayValue()
	{
		return booleanArrayValue;
	}

	/**
	 * @return
	 */
	public boolean isBooleanValue()
	{
		return booleanValue;
	}

	/**
	 * @return
	 */
	public char[] getCharArrayValue()
	{
		return charArrayValue;
	}

	/**
	 * @return
	 */
	public char getCharValue()
	{
		return charValue;
	}

	/**
	 * @return
	 */
	public double[] getDoubleArrayValue()
	{
		return doubleArrayValue;
	}

	/**
	 * @return
	 */
	public double getDoubleValue()
	{
		return doubleValue;
	}

	/**
	 * @return
	 */
	public float[] getFloatArrayValue()
	{
		return floatArrayValue;
	}

	/**
	 * @return
	 */
	public float getFloatValue()
	{
		return floatValue;
	}

	/**
	 * @return
	 */
	public int[] getIntArrayValue()
	{
		return intArrayValue;
	}

	/**
	 * @return
	 */
	public int getIntValue()
	{
		return intValue;
	}

	/**
	 * @return
	 */
	public long[] getLongArrayValue()
	{
		return longArrayValue;
	}

	/**
	 * @return
	 */
	public long getLongValue()
	{
		return longValue;
	}

	/**
	 * @return
	 */
	public Date[] getObjectArrayValue()
	{
		return objectArrayValue;
	}

	/**
	 * @return
	 */
	public Hashtable getObjectValue()
	{
		return objectValue;
	}

	/**
	 * @return
	 */
	public short[] getShortArrayValue()
	{
		return shortArrayValue;
	}

	/**
	 * @return
	 */
	public short getShortValue()
	{
		return shortValue;
	}

	/**
	 * @return
	 */
	public String[] getStringArrayValue()
	{
		return stringArrayValue;
	}

	/**
	 * @return
	 */
	public String getStringValue()
	{
		return stringValue;
	}

	/**
	 * @param bs
	 */
	public void setBooleanArrayValue(boolean[] bs)
	{
		booleanArrayValue2 = bs;
	}

	/**
	 * @param b
	 */
	public void setBooleanValue(boolean b)
	{
		booleanValue2 = b;
	}

	/**
	 * @param cs
	 */
	public void setCharArrayValue(char[] cs)
	{
		charArrayValue2 = cs;
	}

	/**
	 * @param c
	 */
	public void setCharValue(char c)
	{
		charValue2 = c;
	}

	/**
	 * @param ds
	 */
	public void setDoubleArrayValue(double[] ds)
	{
		doubleArrayValue2 = ds;
	}

	/**
	 * @param d
	 */
	public void setDoubleValue(double d)
	{
		doubleValue2 = d;
	}

	/**
	 * @param fs
	 */
	public void setFloatArrayValue(float[] fs)
	{
		floatArrayValue2 = fs;
	}

	/**
	 * @param f
	 */
	public void setFloatValue(float f)
	{
		floatValue2 = f;
	}

	/**
	 * @param is
	 */
	public void setIntArrayValue(int[] is)
	{
		intArrayValue2 = is;
	}

	/**
	 * @param i
	 */
	public void setIntValue(int i)
	{
		intValue2 = i;
	}

	/**
	 * @param ls
	 */
	public void setLongArrayValue(long[] ls)
	{
		longArrayValue2 = ls;
	}

	/**
	 * @param l
	 */
	public void setLongValue(long l)
	{
		longValue2 = l;
	}

	/**
	 * @param buffers
	 */
	public void setObjectArrayValue(Object[] buffers)
	{
		objectArrayValue2 = buffers;
	}

	/**
	 * @param hashtable
	 */
	public void setObjectValue(Hashtable hashtable)
	{
		objectValue2 = hashtable;
	}

	/**
	 * @param ses
	 */
	public void setShortArrayValue(short[] ses)
	{
		shortArrayValue2 = ses;
	}

	/**
	 * @param s
	 */
	public void setShortValue(short s)
	{
		shortValue2 = s;
	}

	/**
	 * @param strings
	 */
	public void setStringArrayValue(String[] strings)
	{
		stringArrayValue2 = strings;
	}

	/**
	 * @param string
	 */
	public void setStringValue(String string)
	{
		stringValue2 = string;
	}

	/**
	 * @return
	 */
	public byte[] getByteArrayValue()
	{
		return byteArrayValue;
	}

	/**
	 * @return
	 */
	public byte getByteValue()
	{
		return byteValue;
	}

	/**
	 * @param bs
	 */
	public void setByteArrayValue(byte[] bs)
	{
		byteArrayValue2 = bs;
	}

	/**
	 * @param b
	 */
	public void setByteValue(byte b)
	{
		byteValue2 = b;
	}

}




Form1.frm
=========

VERSION 5.00
Begin VB.Form Form1
   Caption         =   "Form1"
   ClientHeight    =   3450
   ClientLeft      =   60
   ClientTop       =   345
   ClientWidth     =   6075
   LinkTopic       =   "Form1"
   ScaleHeight     =   3450
   ScaleWidth      =   6075
   StartUpPosition =   3  'Windows Default
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit

Private Sub Form_Load()
    Dim factory As Object
    Set factory = CreateObject("VbParamTestFactory.Bean.1")
    Dim jparam As Object
    Set jparam = factory.createJavaObject("com.vnu.publitec.vbwrapper.paramTest")
    
    
    Dim intTest As Long
    
    Dim byteTest As Byte
    
    Dim byteArrayTest() As Byte
        
    Dim charArrayTest() As Integer
    
    Dim longArrayTest() As Long
    
    'Dim multiArrayTest() As Long
    Dim multiArrayTest() As Object
    
    Dim objectArrayTest() As Object
    
    intTest = jparam.getIntValue
    
    byteTest = jparam.getByteValue
    
    'byteArrayTest = jparam.getByteArrayValue
    ReDim byteArrayTest(2)
    byteArrayTest(0) = 0
    byteArrayTest(1) = 2
    byteArrayTest(2) = 5
    
    'charArrayTest = jparam.getCharArrayValue
    ReDim charArrayTest(2)
    charArrayTest(0) = 0
    charArrayTest(1) = 2
    charArrayTest(2) = 5
    
    'longArrayTest = jparam.getLongArrayValue
    ReDim longArrayTest(2)
    longArrayTest(0) = 0
    longArrayTest(1) = 2
    longArrayTest(2) = 5
    
    multiArrayTest = jparam.getMultiArray
    
    'ReDim multiArrayTest(1, 1)
    'multiArrayTest(0, 0) = 1
    'multiArrayTest(0, 1) = 2
    'multiArrayTest(1, 0) = 3
    'multiArrayTest(1, 1) = 4
    
    
    objectArrayTest = jparam.getObjectArrayValue
    
    jparam.setByteValue byteTest
    'jparam.setByteArrayValue byteArrayTest
    'jparam.setCharArrayValue charArrayTest
    'jparam.setLongArrayValue longArrayTest
    'jparam.setMultiArray multiArrayTest
    jparam.setObjectArrayValue objectArrayTest
    jparam.setLongValue 5
End Sub

---------- END SOURCE ----------
(Incident Review ID: 194010) 
======================================================================


Name: gm110360			Date: 11/04/2003


FULL PRODUCT VERSION :
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)

FULL OS VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

EXTRA RELEVANT SYSTEM CONFIGURATION :
Microsoft Visual Basic 6.0 Pro (service pack 5)
Microsoft Visual C++ 6.0 Pro (service pack 5)

A DESCRIPTION OF THE PROBLEM :
While working on exposing a Java object layer to a VB ui application, I have experienced some restrictions in the Active-X bridge.

The bridge does not support the following java types as parameters or return types of methods called across the Active-X bridge:

Object[]
byte[]
char[]
long[]
Any array of dimensionality higher than 1

Returning these types from a java method results in an automation error being reported by VB. Deeper exploration of the issue showed the following:

Object[]:
Single dimensional arrays of java Objects can be returned from Java methods, but passing arrays of Objects back to Java as a parameter fails. This happens for both the original array received from an earlier Java method call, and for Object arrays created in VB and filled with Java objects.
String arrays are handled separately, and work correctly.

byte[], char[], long[]:
The value is returned as an array of Unsupported Variants. char and long in non-array form can be returned correctly as Integer and Long types.

Multi-dimensional arrays:
The value is returned as a single dimensional array of Objects.


The multi-dimensional array issue can only be tested using methods on java objects returned from packaged beans. Having a method that has a multi-dimensional array parameter or return value on a packaged bean renders in non-instantiatable from VB.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the java source files below into a Jar
Package the VbParamTestFactory bean from the Jar
Create a VB6 project with the provided VB6 code
Uncomment any of the commented out methods in the VB6 code to see the specific error happen.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No error should have been reported if the datatypes were properly supported by the Active-X bridge.
ACTUAL -
returning byte[] or char[] from a java method:
Runtime error 13: Type mismatch

returning long[] from a java method:
Automation error
The object invoked has disconnected from its clients.


passing Object[] to a java method:
The java method receives an array of DispatchImpl type objects.

passing byte[], char[] or long[] to a java method:
java.lang.Exception: setByteArrayValue{0} :no such method exists
java.lang.Exception: setCharArrayValue{0} :no such method exists
java.lang.Exception: setLongArrayValue{0} :no such method exists

passing a multi-dimensional array to a java method:
java.lang.Exception: setMultiArray{0} :no such method exists

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.Exception: setByteArrayValue{0} :no such method exists
	at sun.plugin.com.JavaClass.getMethod1(Unknown Source)
	at sun.plugin.com.JavaClass.getDispatcher(Unknown Source)
	at sun.plugin.com.DispatchImpl.invoke(Unknown Source)

java.lang.Exception: setCharArrayValue{0} :no such method exists
	at sun.plugin.com.JavaClass.getMethod1(Unknown Source)
	at sun.plugin.com.JavaClass.getDispatcher(Unknown Source)
	at sun.plugin.com.DispatchImpl.invoke(Unknown Source)

java.lang.Exception: setLongArrayValue{0} :no such method exists
	at sun.plugin.com.JavaClass.getMethod1(Unknown Source)
	at sun.plugin.com.JavaClass.getDispatcher(Unknown Source)
	at sun.plugin.com.DispatchImpl.invoke(Unknown Source)

java.lang.Exception: setMultiArray{0} :no such method exists
	at sun.plugin.com.JavaClass.getMethod1(Unknown Source)
	at sun.plugin.com.JavaClass.getDispatcher(Unknown Source)
	at sun.plugin.com.DispatchImpl.invoke(Unknown Source)



REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
VbParamTestFactory.java
=======================

package com.vnu.publitec.vbwrapper;

/**
 * @author vbWrapper
 */
public class VbParamTestFactory
{
	public VbParamTestFactory()
	{
		super();
	}

	public Object createJavaObject(String className)
		throws InstantiationException, IllegalAccessException, ClassNotFoundException
	{
		return Class.forName(className).newInstance();
	}
}



paramTest.java
==============

package com.vnu.publitec.vbwrapper;

import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;

/**
 * @author maarten
 */
public class paramTest
{
	private byte byteValue = 7;
	private short shortValue = 135;
	private int intValue = 1241;
	private long longValue = 1535412461;
	private char charValue = 'a';
	private float floatValue = 9.7234527f;
	private double doubleValue = Math.PI;
	private boolean booleanValue = true;
	private String stringValue = "This is a Java String";
	private Hashtable objectValue = new Hashtable();
	private byte[] byteArrayValue = {7, 8, 9};
	private short[] shortArrayValue = {135, 136, 137};
	private int[] intArrayValue = {1241, 1242, 1243, 1244};
	private long[] longArrayValue = {1535412461, 1535412462, 1535412463, 1535412464, 1535412465};
	private char[] charArrayValue = {'a', 'z'};
	private float[] floatArrayValue = {9.7234527f, 123.14f, 1351.245623f};
	private double[] doubleArrayValue = {Math.PI, Math.E};
	private boolean[] booleanArrayValue = {true, false, true};
	private String[] stringArrayValue = {"This is a Java String", "Another Java String", ""};
	private Date[] objectArrayValue = {new Date(), new Date(14513246)};
	
	private byte byteValue2;
	private short shortValue2;
	private int intValue2;
	private long longValue2;
	private char charValue2;
	private float floatValue2;
	private double doubleValue2;
	private boolean booleanValue2;
	private String stringValue2;
	private Hashtable objectValue2;
	private byte[] byteArrayValue2;
	private short[] shortArrayValue2;
	private int[] intArrayValue2;
	private long[] longArrayValue2;
	private char[] charArrayValue2;
	private float[] floatArrayValue2;
	private double[] doubleArrayValue2;
	private boolean[] booleanArrayValue2;
	private String[] stringArrayValue2;
	private Object[] objectArrayValue2;
	
	private int[][] multiArray = {{1,2},{3,4}};
	
	
	public paramTest()
	{
		super();
	}
	
	public int[][] getMultiArray()
	{
		return multiArray;
	}
	
	public void setMultiArray(int[][] ma)
	{
		multiArray = ma;
	}
	
	public String report()
	{
		String report = "";
		
		// Single value tests
		if (booleanValue == booleanValue2)
		{
			report += "boolean value identical: " + booleanValue + " - " + booleanValue2 + "\r\n";
		}
		else
		{
			report += "boolean value not identical: " + booleanValue + " - " + booleanValue2 + "\r\n";
		}
		if (charValue == charValue2)
		{
			report += "char value identical: " + charValue + " - " + charValue2 + "\r\n";
		}
		else
		{
			report += "char value not identical: " + charValue + " - " + charValue2 + "\r\n";
		}
		if (doubleValue == doubleValue2)
		{
			report += "double value identical: " + doubleValue + " - " + doubleValue2 + "\r\n";
		}
		else
		{
			report += "double value not identical: " + doubleValue + " - " + doubleValue2 + "\r\n";
		}
		if (floatValue == floatValue2)
		{
			report += "float value identical: " + floatValue + " - " + floatValue2 + "\r\n";
		}
		else
		{
			report += "float value not identical: " + floatValue + " - " + floatValue2 + "\r\n";
		}
		if (intValue == intValue2)
		{
			report += "int value identical: " + intValue + " - " + intValue2 + "\r\n";
		}
		else
		{
			report += "int value not identical: " + intValue + " - " + intValue2 + "\r\n";
		}
		if (longValue == longValue2)
		{
			report += "long value identical: " + longValue + " - " + longValue2 + "\r\n";
		}
		else
		{
			report += "long value not identical: " + longValue + " - " + longValue2 + "\r\n";
		}
		if (shortValue == shortValue2)
		{
			report += "short value identical: " + shortValue + " - " + shortValue2 + "\r\n";
		}
		else
		{
			report += "short value not identical: " + shortValue + " - " + shortValue2 + "\r\n";
		}

		if (stringValue == stringValue2)
		{
			report += "string value identical: " + stringValue + " - " + stringValue2 + "\r\n";
		}
		else
		{
			report += "string value not identical: " + stringValue + " - " + stringValue2 + "\r\n";
		}
		if (stringValue.equals(stringValue2))
		{
			report += "string value equal: " + stringValue + " - " + stringValue2 + "\r\n";
		}
		else
		{
			report += "string value not equal: " + stringValue + " - " + stringValue2 + "\r\n";
		}

		if (objectValue == objectValue2)
		{
			report += "object value identical: " + objectValue + " - " + objectValue2 + "\r\n";
		}
		else
		{
			report += "object value not identical: " + objectValue + " - " + objectValue2 + "\r\n";
		}
		if (objectValue.equals(objectValue2))
		{
			report += "object value equal: " + objectValue + " - " + objectValue2 + "\r\n";
		}
		else
		{
			report += "object value not equal: " + objectValue + " - " + objectValue2 + "\r\n";
		}
		
		
		
		
		
		// Array identity tests
		if (booleanArrayValue == booleanArrayValue2)
		{
			report += "boolean array value identical: " + booleanArrayValue + " - " + booleanArrayValue2 + "\r\n";
		}
		else
		{
			report += "boolean array value not identical: " + booleanArrayValue + " - " + booleanArrayValue2 + "\r\n";
		}
		if (Arrays.equals(booleanArrayValue, booleanArrayValue2))
		{
			report += "boolean array value equal: " + booleanArrayValue + " - " + booleanArrayValue2 + "\r\n";
		}
		else
		{
			report += "boolean array value not equal: " + booleanArrayValue + " - " + booleanArrayValue2 + "\r\n";
		}
/*		if (charArrayValue == charArrayValue2)
		{
			report += "char array value identical: " + new String(charArrayValue) + " - " + new String(charArrayValue2) + "\r\n";
		}
		else
		{
			report += "char array value not identical: " + new String(charArrayValue) + " - " + new String(charArrayValue2) + "\r\n";
		}
		if (Arrays.equals(charArrayValue, charArrayValue2))
		{
			report += "char array value equal: " + new String(charArrayValue) + " - " + new String(charArrayValue2) + "\r\n";
		}
		else
		{
			report += "char array value not equal: " + new String(charArrayValue) + " - " + new String(charArrayValue2) + "\r\n";
		}
*/		if (doubleArrayValue == doubleArrayValue2)
		{
			report += "double array value identical: " + doubleArrayValue + " - " + doubleArrayValue2 + "\r\n";
		}
		else
		{
			report += "double array value not identical: " + doubleArrayValue + " - " + doubleArrayValue2 + "\r\n";
		}
		if (Arrays.equals(doubleArrayValue, doubleArrayValue2))
		{
			report += "double array value equal: " + doubleArrayValue + " - " + doubleArrayValue2 + "\r\n";
		}
		else
		{
			report += "double array value not equal: " + doubleArrayValue + " - " + doubleArrayValue2 + "\r\n";
		}
		if (floatArrayValue == floatArrayValue2)
		{
			report += "float array value identical: " + floatArrayValue + " - " + floatArrayValue2 + "\r\n";
		}
		else
		{
			report += "float array value not identical: " + floatArrayValue + " - " + floatArrayValue2 + "\r\n";
		}
		if (Arrays.equals(floatArrayValue, floatArrayValue2))
		{
			report += "float array value equal: " + floatArrayValue + " - " + floatArrayValue2 + "\r\n";
		}
		else
		{
			report += "float array value not equal: " + floatArrayValue + " - " + floatArrayValue2 + "\r\n";
		}
		if (intArrayValue == intArrayValue2)
		{
			report += "int array value identical: " + intArrayValue + " - " + intArrayValue2 + "\r\n";
		}
		else
		{
			report += "int array value not identical: " + intArrayValue + " - " + intArrayValue2 + "\r\n";
		}
		if (Arrays.equals(intArrayValue, intArrayValue2))
		{
			report += "int array value equal: " + intArrayValue + " - " + intArrayValue2 + "\r\n";
		}
		else
		{
			report += "int array value not equal: " + intArrayValue + " - " + intArrayValue2 + "\r\n";
		}
/*		if (longArrayValue == longArrayValue2)
		{
			report += "long array value identical: " + longArrayValue + " - " + longArrayValue2 + "\r\n";
		}
		else
		{
			report += "long array value not identical: " + longArrayValue + " - " + longArrayValue2 + "\r\n";
		}
		if (Arrays.equals(longArrayValue, longArrayValue2))
		{
			report += "long array value equal: " + longArrayValue + " - " + longArrayValue2 + "\r\n";
		}
		else
		{
			report += "long array value not equal: " + longArrayValue + " - " + longArrayValue2 + "\r\n";
		}
*/		if (shortArrayValue == shortArrayValue2)
		{
			report += "short array value identical: " + shortArrayValue + " - " + shortArrayValue2 + "\r\n";
		}
		else
		{
			report += "short array value not identical: " + shortArrayValue + " - " + shortArrayValue2 + "\r\n";
		}
		if (Arrays.equals(shortArrayValue, shortArrayValue2))
		{
			report += "short array value equal: " + shortArrayValue + " - " + shortArrayValue2 + "\r\n";
		}
		else
		{
			report += "short array value not equal: " + shortArrayValue + " - " + shortArrayValue2 + "\r\n";
		}


		if (stringArrayValue == stringArrayValue2)
		{
			report += "string array value identical: " + stringArrayValue + " - " + stringArrayValue2 + "\r\n";
		}
		else
		{
			report += "string array value not identical: " + stringArrayValue + " - " + stringArrayValue2 + "\r\n";
		}
		if (Arrays.equals(stringArrayValue, stringArrayValue2))
		{
			report += "string array value equal: " + stringArrayValue + " - " + stringArrayValue2 + "\r\n";
		}
		else
		{
			report += "string array value not equal: " + stringArrayValue + " - " + stringArrayValue2 + "\r\n";
		}
		for (int i = 0; i < stringArrayValue.length; i++)
		{
			String string1 = stringArrayValue[i];
			String string2 = stringArrayValue2[i];
			
			if (string1 == string2)
			{
				report += "string array content value identical: " + string1 + " - " + string2 + "\r\n";
			}
			else
			{
				report += "string array content value not identical: " + string1 + " - " + string2 + "\r\n";
			}
			if (string1.equals(string2))
			{
				report += "string array content value equal: " + string1 + " - " + string2 + "\r\n";
			}
			else
			{
				report += "string array content value not equal: " + string1 + " - " + string2 + "\r\n";
			}
		}

/*		if (objectArrayValue == objectArrayValue2)
		{
			report += "object array value identical: " + objectArrayValue + " - " + objectArrayValue2 + "\r\n";
		}
		else
		{
			report += "object array value not identical: " + objectArrayValue + " - " + objectArrayValue2 + "\r\n";
		}
		if (Arrays.equals(objectArrayValue, objectArrayValue2))
		{
			report += "object array value equal: " + objectArrayValue + " - " + objectArrayValue2 + "\r\n";
		}
		else
		{
			report += "object array value not equal: " + objectArrayValue + " - " + objectArrayValue2 + "\r\n";
		}
		for (int i = 0; i < objectArrayValue.length; i++)
		{
			Object object1 = objectArrayValue[i];
			Object object2 = objectArrayValue2[i];
			
			if (object1 == object2)
			{
				report += "object array content value identical: " + object1 + " - " + object2 + "\r\n";
			}
			else
			{

Comments
EVALUATION There are three problems described in this bug report 1) Unable to pass arrays of type Object, long, char and byte into java methods 2) Arrays of type byte, long and char are returned as array of unsupported variants 3) Multi-dimensional arrays are not supported by the bridge The first problem has been fixed in tiger as a result of fix for #4887461. To understand the second problem, let us compare the byte sizes for data types in VB and Java In case of VB, Long - 4 byte signed integer Integer - 2 byte signed integer Byte - 1 byte unsigned integer In case of Java, long - 8 byte signed integer char - 2 byte unsigned integer(16 bit unicode) byte - 1 byte signed integer The ActiveX bridge mapping for Java-->COM is as follows byte -> VT_I1 char -> VT_UI2 long -> VT_I8 The data types corresponding to VT_I1, VT_UI2 and VT_I8 are not available in visual basic and hence we see the error messages. The third issue is a known problem. I have filed a new RFE #4950998 against this issue. Since the second issue is not really a bug in the ActiveX bridge. I will close this bug as a duplicate of #4887461 ###@###.### 2003-11-07
07-11-2003