class Test (in unnamed module #0x33f88ab) cannot access class com.sun.media.sound.FFT (in module java.desktop) - kotlin

I want to use musicg to analysis audio fingerprint.
But I got following error in musicg library.
IllegalAccessError: class Test
(in unnamed module #0x33f88ab) cannot access class com.sun.media.sound.FFT
(in module java.desktop)
because module java.desktop does not export com.sun.media.sound to unnamed module #0x33f88ab
What should I do?
Environment
Kotlin
JDK 17(downgrade available)
musicg 1.4.2.2
My code
fun main(args: Array<String>) {
FFT(10, 20)
}
got exception in FFT(10, 20)

com.sun and its sub-packages are not part of the public Java API. They implement some standard Java APIs, but you shouldn't refer to them directly. (They're likely to change and/or be renamed or removed between JVM releases, and non-Sun/Oracle JVMs probably won't have them at all.)
In most cases you should access the public API classes (e.g. in javax.sound) instead. (Those may use sun.*/com.sun.*/etc. classes internally as needed, but that's merely an implementation detail.)
In early versions of Java, there was nothing to stop people using those internal implementation classes, and so some developers got into bad habits. But Java 9 added a module system, which restricts access to them. The error message you see is a result of that.
The details are in JEP 260. The intent was that there would be public APIs for all of the critical APIs that were being restricted. However, according to this Oracle forum page, the work wasn't completed, and so there are some internal APIs for which no public equivalent exists yet.
FFT looks like one of those classes that has been overlooked. I can't see a direct replacement for it, I'm afraid. Is there a third-party library you can use? This question gives some options.

Related

Kotlin 1.7 dependency resolution

Assume I have gradle mudule structure like that: module1 => module2 => gson.
Module2 exposes gson as a return type in one of its public interfaces' methods but it's never used in module1. The dependencies are provided using
implementation
configuration. the question is should I provide gson dependency to module1 considering it's not used there or not? is there any standard for this? I'm asking because in kotlin 1.6.10 it works fine but kotlin 1.7.20 seems to break it and during dagger2 processing step I get an error like this:
ComponentProcessingStep was unable to process
'module1.MyComponent' because
'Gson'
could not be resolved.
This is what an api (instead of implementation) dependency is for in gradle. Just replace implementation("gson:...") with api("gson:...")
See https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation
So when should you use the api configuration? An API dependency is one that contains at least one type that is exposed in the library binary interface, often referred to as its ABI (Application Binary Interface). This includes, but is not limited to:
types used in super classes or interfaces
types used in public method parameters, including generic parameter types (where public is something that is visible to compilers. I.e. , public, protected and package private members in the Java world)
...
The latter is your use case.
As for why dagger didn't complain in 1.6, I wouldn't know, in any case it was wrong in 1.6 as well, you just got lucky that nothing tripped over it.

What is the purpose of actual keyword in Kotlin

I noticed that some functions for coroutines are marked with actual keyword.
From documentation:
actual denotes a platform-specific implementation in multiplatform
projects
As I understood from documentation actual keyword is used for multiplatform projects and should work in pair with expect keyword.
Something like this:
Common module:
package org.jetbrains.foo
expect class Foo(bar: String) {
fun frob()
}
fun main(args: Array<String>) {
Foo("Hello").frob()
}
Corresponding module:
package org.jetbrains.foo
actual class Foo actual constructor(val bar: String) {
actual fun frob() {
println("Frobbing the $bar")
}
}
That case is clear.
But in package kotlinx.coroutines.experimental I noticed that some functions like launch or withContext are marked as actual but there are no expect functions in package.
So what is the purpose of actual keyword without expect?
The kotlinx.coroutines library actually makes use of multiplatform projects since it supports both the JVM and JS compilation targets.
You can find the common module here, and the specific expect declarations for the functions you've mentioned here.
While the source code in the other answer helped, I found this page (linked off of the page #jim-andreas mentioned in the comments above) was much more helpful.
Specifically, this passage:
If you're developing a multiplatform application that needs to access platform-specific APIs that implement the required functionality (for example, generating a UUID), use the Kotlin mechanism of expected and actual declarations.
With this mechanism, a common source set defines an expected
declaration, and platform source sets must provide the actual
declaration that corresponds to the expected declaration. This works
for most Kotlin declarations, such as functions, classes, interfaces,
enumerations, properties, and annotations.
The compiler ensures that every declaration marked with the expect keyword in the common module has the corresponding declarations marked with the actual keyword in all platform modules. The IDE provides tools that help you create the missing actual declarations.
Again, for more information, you can visit this page.

How to extend java classes on in Python with JPype as its interfacing mechanism with java?

I use JPype to build a SOAP client in my python based test platform. However, I need to extend a Java class to make a call like this:
Like
void process(Context parameter)
The type Context here is a class and to give an implementation, I need to extend Context in python using JPype.
class MyContext extends Context { //override the methods}
With JProxy functionality (in JPype), I'm able to "implement" java interfaces.
But I want to extend a class not an interface. Any help is appreciated.
This very much a limitation. JPype does not allow sub-classing.
sourceforge link
Changed the SOAP method to accept an interface in the API contract.
JPype is an effort to allow Python programs full access to Java class libraries. This is achieved not through re-implementing Python, as Jython/JPython has done, but rather through interfacing at the native level in both virtual machines.
Eventually, it should be possible to replace Java with Python in many, though not all, situations. JSP, Servlets, RMI servers and IDE plugins are all good candidates.
Once this integration is achieved, a second phase will be started to separate the Java logic from the Python logic, eventually allowing the bridging technology to be used in other environments, i.e. Ruby, Perl, COM, etc ..

Javassist NotFoundException when getting java.io.Serializable with JDK9

I have the following code:
private static CtClass resolveCtClass(String clazz) throws NotFoundException {
ClassPool pool = ClassPool.getDefault();
return pool.get( clazz );
}
When running under JDK8, if this method is called using java.io.Serializable, it works, but when running under the JDK9 environment, it throws the NotFoundException.
Is there something I overlooked here?
This does no longer happen with the current EA builds of Java 9. Class files are now always locatable even if they are encapsulated in a module.
This is a consequence of Java 9's module encapsulation where non-exported resources are no longer available via the ClassLoader API. Under the covers, Javassist calls
ClassLoader.getSystemClassLoader().findResource("java/io/Serializable.class");
to get hold of the class file for Serializable. It then parses this class file and represents the information similarly to the Java reflection API but without loading the class such that it can be edited prior to loading it.
Until Java 8, this class file was accessible as most class loaders rely on looking up a class file before loading it such that the above call returned a URL pointing to the file. Since Java 9, resources of named modules are only available via the new API method findResource(String, String) where the second arguments names the module of that class.
The short answer is: Javassist does no longer work with Java 9 and none of its dependant projects will. This is a known issue with the current Java 9 implementation and will hopefully be fixed prior to release.
(I never used Javassist so I'm just shooting in the dark, here...)
The documentation of ClassPool says:
If get() is called on this object, it searches various sources represented by ClassPath to find a class file and then it creates a CtClass object representing that class file.
This seems to be bound to the concept of the class path. Looking at ClassPath and CtClass supports that assumption.
If that is the case, then Javassist might just not be fit to look into JDK 9's brand new modules.
If my guess is correct, you should not be able to get any JDK class from the pool. This should be easily verifiable.

How to disable proguard in javafxports for errors "You should consider keeping the * attributes"

I'm trying to use JavaFX in my android device, with the help of javafxports.
I used the XStream to parse some XML file in my program.
When i compile them, the javafxports outputs the following warnings:
Note: there were 9 classes trying to access annotations using reflection.
You should consider keeping the annotation attributes
(using '-keepattributes *Annotation*').
(http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)
Note: there were 32 classes trying to access generic signatures using reflection.
You should consider keeping the signature attributes
(using '-keepattributes Signature').
(http://proguard.sourceforge.net/manual/troubleshooting.html#attributes)
Note: there were 56 unresolved dynamic references to classes or interfaces.
You should check if you need to specify additional program jars.
(http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclass)
Note: there were 3 class casts of dynamically created class instances.
You might consider explicitly keeping the mentioned classes and/or
their implementations (using '-keep').
(http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclasscast)
Note: there were 39 accesses to class members by means of introspection.
You should consider explicitly keeping the mentioned class members
(using '-keep' or '-keepclassmembers').
(http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclassmember)
Note: you're ignoring all warnings!
The output .apk can be installed and run until it calls the xstream classes to read annotations in my classes. The reason is actually described in the warnings.
So my question is, how can i disable the proguard when generating .apk, or send it a custom proguard.pro configuration.
And my build.gradle is almost the same as that in the helloworld example.
Thanks.