s-u / rJava

R to Java interface
https://RForge.net/rJava
235 stars 77 forks source link

wrong class in method signatures #306

Closed eheisman closed 1 year ago

eheisman commented 1 year ago

I am getting an error when trying to call a function that no method can be found with the signature. I've tried two different ways,

>   output = ets$computeSingleValueSummary(.jcast(twoStep, "hec/ensemble/stats/SingleComputable", check=T))
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl,  : 
  java.lang.NoSuchMethodException: No suitable method for the given parameters

and

>   output = .jcall(ets, returnSig="hec/metrics/MetricCollectionTimeSeries", method="computeSingleValueSummary", twoStep)
Error in .jcall(ets, returnSig = "hec/metrics/MetricCollectionTimeSeries",  : 
  method computeSingleValueSummary with signature (Lhec/ensemble/stats/SingleComputable;)hec/metrics/MetricCollectionTimeSeries not found

Looking at the methods listed out by the .jmethods function, it appears that the word "ensemble" is getting dropped from some of the package names on method signatures.

.jmethods(ets)
 [1] "public java.util.Iterator hec.ensemble.EnsembleTimeSeries.iterator()"                                                                                         
 [2] "public void hec.ensemble.EnsembleTimeSeries.addEnsemble(java.time.ZonedDateTime,float[][],java.time.ZonedDateTime,java.time.Duration,java.lang.String)"       
 [3] "public void hec.ensemble.EnsembleTimeSeries.addEnsemble(hec.ensemble.Ensemble)"                                                                               
 [4] "public java.lang.String hec.ensemble.EnsembleTimeSeries.getUnits()"                                                                                           
 [5] "public java.util.List hec.ensemble.EnsembleTimeSeries.getIssueDates()"                                                                                        
 [6] "public java.lang.String hec.ensemble.EnsembleTimeSeries.getDataType()"                                                                                        
 [7] "public hec.metrics.MetricCollectionTimeSeries hec.ensemble.EnsembleTimeSeries.iterateAcrossEnsembleTracesWithSingleComputable(hec.stats.Computable)"          
 [8] "public hec.metrics.MetricCollectionTimeSeries hec.ensemble.EnsembleTimeSeries.iterateTracesOfEnsemblesWithMultiComputable(hec.stats.MultiComputable)"         
 [9] "public hec.metrics.MetricCollectionTimeSeries hec.ensemble.EnsembleTimeSeries.iterateAcrossTracesOfEnsemblesWithMultiComputable(hec.stats.MultiComputable)"   
[10] "public hec.metrics.MetricCollectionTimeSeries hec.ensemble.EnsembleTimeSeries.computeSingleValueSummary(hec.stats.SingleComputable)"                          
[11] "public hec.RecordIdentifier hec.ensemble.EnsembleTimeSeries.getTimeSeriesIdentifier()"                                                                        
[12] "public int hec.ensemble.EnsembleTimeSeries.getCount()"                                                                                                        
[13] "public java.lang.String hec.ensemble.EnsembleTimeSeries.getVersion()"                                                                                         
[14] "public hec.ensemble.Ensemble hec.ensemble.EnsembleTimeSeries.getEnsemble(java.time.ZonedDateTime)"                                                            
[15] "public hec.metrics.MetricCollectionTimeSeries hec.ensemble.EnsembleTimeSeries.iterateAcrossTimestepsOfEnsemblesWithMultiComputable(hec.stats.MultiComputable)"
[16] "public hec.metrics.MetricCollectionTimeSeries hec.ensemble.EnsembleTimeSeries.iterateAcrossTimestepsOfEnsemblesWithSingleComputable(hec.stats.Computable)"    
[17] "public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException"                                                                   
[18] "public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException"                                                                      
[19] "public final void java.lang.Object.wait() throws java.lang.InterruptedException"                                                                              
[20] "public boolean java.lang.Object.equals(java.lang.Object)"                                                                                                     
[21] "public java.lang.String java.lang.Object.toString()"                                                                                                          
[22] "public native int java.lang.Object.hashCode()"                                                                                                                
[23] "public final native java.lang.Class java.lang.Object.getClass()"                                                                                              
[24] "public final native void java.lang.Object.notify()"                                                                                                           
[25] "public final native void java.lang.Object.notifyAll()"                                                                                                        
[26] "public default java.util.Spliterator java.lang.Iterable.spliterator()"                                                                                        
[27] "public default void java.lang.Iterable.forEach(java.util.function.Consumer)"                                                                                  
> J("hec/ensemble/stats/SingleComputable")
[1] "Java-Class-Name: hec.ensemble.stats.SingleComputable"
> .jmethods(.Last.value)
[1] "public abstract float hec.ensemble.stats.SingleComputable.compute(float[][])"                        
[2] "public abstract hec.ensemble.stats.Statistics[] hec.ensemble.stats.StatisticsReportable.Statistics()"
[3] "public abstract java.lang.String hec.ensemble.stats.StatisticsReportable.StatisticsLabel()"          
> J("hec/stats/SingleComputable")
[1] "Java-Class-Name: hec.stats.SingleComputable"
> .jmethods(.Last.value)
[1] "public abstract float hec.stats.SingleComputable.compute(float[][])"               
[2] "public abstract hec.stats.Statistics[] hec.stats.StatisticsReportable.Statistics()"

The class I am listing methods from has the correct imports, and while a hec.stats package exists elsewhere, it shouldn't be available in this environment.

I should also note that the .jnew function was not working for me on classes in the hec.ensemble.stats package, but I was able to create them using `new(J("hec.ensemble.stats.[...]")).

Something seems to be off with the class loading process. Any suggestions as to what might be causing this?

eheisman commented 1 year ago

Well, the tests in the package declare themselves to be part of the hec.stats package, so I suspect something is throwing this off. Fixing this and rebuilding the .jar did not seem to make a difference.

s-u commented 1 year ago

Not sure wha this has to do with rJava - this is entirely an issue in your JAR files. Check your classpaths - see .jclassPath() and .jaddClassPath(). Java only sees what you load, it's not making things up. You can enable debugging in the class loader to see what exactly is loaded from where via .jclassLoader()$setDebug(1L).

eheisman commented 1 year ago

Thanks for that tip - I was figuring some introspection would help me figure it out. It looks like an old copy of the R package this code wraps was being loaded along with an old .jar of the problem code.

s-u commented 1 year ago

Note that since rJava 1.0 you can use .jpackage(..., own.loader=TRUE) which will (possibly) avoid similar issues by making sure your package is using a separate loader so it won't mix with other packages (or versions).

eheisman commented 1 year ago

It was definitely a problem with the classpath having an old copy of the .jar I was interfacing with loaded via an old version of my package. Much appreciate the few moments you took to address this.