I guess I have to violate the license (and I don't feel bad...)

M

Michael Wurm

I'm writing a Java-Midi-Karaoke player and for performance
reasons I had to rewrite some classes in javax.sound.midi.
Now I didn't look at the original source code and my classes
are compatible to those defined in the API specification,
they just have a few methods more for optimized use.

Now I didn't mangle around with rt.jar, but I use the
-Xbootclasspath option. This violates the license, but now
I want to publish the source code.

So, what are the options?

[ ] just publish. everyone will be happy, because it's so great.
[ ] like above, but I'm not happy anymore (because of Sun).
[ ] recode more stuff, which is already in the runtime
environment until I get to a point, where I can put the
whole thing into a different package.
[ ] jump out of the 13th floor
[ ] ...

Michael

####
For those, asking why I want to do all this:

It's worth it. My classes load MIDI-files 4 to 50 times faster,
depending on the file, they also load files that do not exactly
meet the MIDI-specification and they are optimized for
MIDI-Files with lyrics.
Some files took about 5 seconds to load on a P1@900 (and that's
inacceptable), now they load in 100ms.

I can't extend the original classes, because some have protected
constructors.
 
B

Bryce

I'm writing a Java-Midi-Karaoke player and for performance
reasons I had to rewrite some classes in javax.sound.midi.
Now I didn't look at the original source code and my classes
are compatible to those defined in the API specification,
they just have a few methods more for optimized use.

Now I didn't mangle around with rt.jar, but I use the
-Xbootclasspath option. This violates the license, but now
I want to publish the source code.

So, what are the options?

Instead of subclass, use the code, but rename the class and package to
your own.
 
R

Roedy Green

[ ] just publish. everyone will be happy, because it's so great.
[ ] like above, but I'm not happy anymore (because of Sun).
[ ] recode more stuff, which is already in the runtime
environment until I get to a point, where I can put the
whole thing into a different package.
[ ] jump out of the 13th floor

Are sun's classes final? If not, simply create a new class and
override the slow methods.

If sun's classes are final you can use the technique I used in
LEDataInputStream. It has an internal Sun DataInputStream object.
There are dozens of wrapper methods that do nothing but call the
equivalent sun method on the delegate. Some do something useful and
then call the sun methods.

see http://mindprod.com/products.html#LEDATASTREAM
 
M

Michael Wurm

Are sun's classes final? If not, simply create a new class and
override the slow methods.

That doesn't work.
I have to specify my problem clearly:
The classes out of javax.sound.midi I have rewritten are
"Sequence" and "Track". I cannot subclass "Track" because the
constructor is protected and for some reason I can only call
is from inside the package (not even from a subclass outside
the package).
But for actual playback I use a Sequencer provided by sun,
which expects javax.sound.midi.Sequence and
javax.sound.midi.Track.
If sun's classes are final you can use the technique I used in
LEDataInputStream. It has an internal Sun DataInputStream object.
There are dozens of wrapper methods that do nothing but call the
equivalent sun method on the delegate. Some do something useful and
then call the sun methods.

See above.

@Bryce ([email protected]):
aren't protected constructors accessible from child classes?

Cite from a java turorial:
"If a class is both a subclass of and in the same package as the
class with the protected member, then the class has access to
the protected member."

And I tried it. I'd have to place the subclass into javax.sound.midi,
with the same licensing problems.


thanks for reply,
Michael
 
X

xarax

Michael Wurm said:
That doesn't work.
I have to specify my problem clearly:
The classes out of javax.sound.midi I have rewritten are
"Sequence" and "Track". I cannot subclass "Track" because the
constructor is protected and for some reason I can only call
is from inside the package (not even from a subclass outside
the package).

That cannot be the reason why you cannot subclass Track.
Perhaps the Track class is package-scoped rather than public?
But for actual playback I use a Sequencer provided by sun,
which expects javax.sound.midi.Sequence and
javax.sound.midi.Track.

Uh, these are the exact same classes that you just
said you were trying to override with your own
subclasses.
See above.

See below.
@Bryce ([email protected]):

Cite from a java turorial:
"If a class is both a subclass of and in the same package as the
class with the protected member, then the class has access to
the protected member."

Irrelevant quote.

In summary:
If the class is package-scoped, then any subclass must also
be a member of the same package. That is, a "foreign" subclass
won't have access to the parent class, so it cannot extend it.

If the class is public, then any subclass from any package can
see the inherited protected members, including protected constructors.
A "foreign-package" subclass cannot see the parent class private
members nor package-scoped members.

Don't ask me to quote chapter and verse, because that's
your job, not mine.
And I tried it. I'd have to place the subclass into javax.sound.midi,
with the same licensing problems.

Something else is wrong, which you haven't yet identified
for us.

I've looked at the JavaDoc for 1.4.2 for Sequence and Track.
The classes are declared non-final and public. Track has no
constructors, so its default constructor is public. Sequence
has two public constructors.

Both classes appear from the JavaDoc to be fully extendable
by any foreign subclass. Is the actual source different from
the JavaDoc?
 
R

Roedy Green

That doesn't work.
I have to specify my problem clearly:
The classes out of javax.sound.midi I have rewritten are
"Sequence" and "Track". I cannot subclass "Track" because the
constructor is protected and for some reason I can only call
is from inside the package (not even from a subclass outside
the package).
But for actual playback I use a Sequencer provided by sun,
which expects javax.sound.midi.Sequence and
javax.sound.midi.Track.

I have gone through this myself and know how frustrating it is when
Sun blocks you at every turn from doing what seem to be perfectly
ordinary things.

The constructor being "protected" is GOOD. That means a subclass, even
in a different package, can access it. If you want to access it from
other classes, they can still do so via your overriding class.

The second problem is frustrating. You can't insert your code in to
replace any lower level code, unless there is provided an explicit
hook for it. This is so easy in some other languages, but in Java is
considered too dangerous.

I wonder if it would be possible to fool it this way.

1. You fire up a custom class loader that gets a copy of your Sequence
and Track from a jar somewhere. They would even have Sun's package
names.

2. Then you load Sun's code for Sequencer. I would then be happy with
your version and would not think to load its own.

Sun may block you from loading classes with its package name even in a
custom class loader.

If that did not work, you could grab the class file for Sequence on
the fly and patch it to use your classes, then load it with a custom
class loader. See http://mindprod.com/jgloss/jasm.html

Has anyone solved this general problem before?
 
M

Michael Wurm

xarax said:
[...]
But for actual playback I use a Sequencer provided by sun,
which expects javax.sound.midi.Sequence and
javax.sound.midi.Track.

Uh, these are the exact same classes that you just
said you were trying to override with your own
subclasses.

I already coded the classes to replace them. As long as the Java-VM
thinks that they are the right classes, it's ok and it works; they
still have the same interface.
[...]
I've looked at the JavaDoc for 1.4.2 for Sequence and Track.
The classes are declared non-final and public. Track has no
constructors, so its default constructor is public. Sequence
has two public constructors.

Both classes appear from the JavaDoc to be fully extendable
by any foreign subclass. Is the actual source different from
the JavaDoc?

Sorry, I was wrong. The constructor has "package"-access, which
causes the same problem.
The intention of this is, that a Sequence is a factory for
Track instances.

Michael

###
javap -c javax.sound.midi.Track
Compiled from "Track.java"
public class javax.sound.midi.Track extends java.lang.Object{
protected java.util.Vector events;

....

javax.sound.midi.Track();
Code:
0: aload_0
1: invokespecial #81; //Method java/lang/Object."<init>":()V

....
 
A

Andrew Thompson

Sun may block you from loading classes with its package name even in a
custom class loader.

That is what my recent experiments concluded.

I was intending to use it to allow people to
reflect upon the older rt.jars. Sun had other
ideas. ;-)
 
R

Roedy Green

Sorry, I was wrong. The constructor has "package"-access, which
causes the same problem.
The intention of this is, that a Sequence is a factory for
Track instances.

Perhaps the way out then is to get yourself registered on Sequencer's
list of possible factory objects. There may even be an official way
to do it.
 
M

Michael Wurm

Roedy Green said:
I have to specify my problem clearly:
The classes out of javax.sound.midi I have rewritten are
"Sequence" and "Track". I cannot subclass "Track" because the
constructor is protected and for some reason I can only call
is from inside the package (not even from a subclass outside
the package).
But for actual playback I use a Sequencer provided by sun,
which expects javax.sound.midi.Sequence and
javax.sound.midi.Track.

[...]

The constructor being "protected" is GOOD. That means a subclass, even
in a different package, can access it. If you want to access it from
other classes, they can still do so via your overriding class.

Now, in this point, I was wrong. Actually it is package-scoped, so no
chance outside of it.
The second problem is frustrating. You can't insert your code in to
replace any lower level code, unless there is provided an explicit
hook for it. This is so easy in some other languages, but in Java is
considered too dangerous.

I wonder if it would be possible to fool it this way.
[...]
Has anyone solved this general problem before?

Yes, I solved it.
But it's illegal to distribute projects using this
technique, and that's my actual problem.

Start java like this:
java -Xbootclasspath/p:myruntime MyApp

In the directory "myruntime" can be a structure like this:
javax/sound/midi/Track.class
javax/sound/midi/Sequence.class

The option -Xbootclasspath/p prepends the specified path (should
also work with a jar-file) to the search pathes for runtime classes.
When loading a RT class, java first searches this directory, and if
there is a class with the required name, it is used. Otherwise java
searches in the default place (rt.jar).
With -Xbootclasspath:myruntime you can completely replace the
default RT.

What does the license say about this?

Excerpt from Sun's license
SUPPLEMENTAL LICENSE TERMS - Section B:
[...] Sun grants you a non-exclusive, non-transferable,
limited license without fees to reproduce and distribute the
Software, provided that [...] (iii)
you do not distribute additional software intended to replace
any component(s) of the Software (unless otherwise specified
in the applicable README file) [...]

From the documentation of the -Xbootclasspath - option:
Note: Applications that use this option for the purpose of
overriding a class in rt.jar should not be deployed as doing
so would contravene the Java 2 Runtime Environment binary code
license.
 
R

Roedy Green

From the documentation of the -Xbootclasspath - option:
Note: Applications that use this option for the purpose of
overriding a class in rt.jar should not be deployed as doing
so would contravene the Java 2 Runtime Environment binary code
license.

They gave you -Xbootclasspath for your own code. You could read that
licence in a different way. So long as you don't wreck the JVM with
mods, you have done nothing wrong. You have not modified the JVM, only
RAM. To me that would be more logical. They don't want you hosing
OTHER apps. There are so many ways to hose your own, why bother trying
to stop you replacing system code? After all you do it every time you
override a public class.

You might ask Sun what they mean or get a lawyer to study the licence.

Perhaps they are trying to protect themselves for a future JVM that
handles several apps at once, where you need more considerate
behaviour.

The other way of looking at it, is what harm comes to Sun from you
using -Xbootclasspath? If they did not want you to use it, why is it
there? There surely must be a principle in law that states you can't
hide irrelevant clauses in computer contracts of the form, "the signer
promises never to wear blue shoes, with penalty of $1,000,000"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top