-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
8
-
x86_64
-
linux
FULL PRODUCT VERSION :
java version "1.8.0_152-ea"
Java(TM) SE Runtime Environment (build 1.8.0_152-ea-b05)
Java HotSpot(TM) 64-Bit Server VM (build 25.152-b05, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux pellet 4.10.0-35-generic #39-Ubuntu SMP Wed Sep 13 07:46:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Calling defineClass(String name, byte[] b, int off, int len) loads the class but not any associated packages.
In Java9, the behaviour is that the package is loaded.
This makes it impossible to write class transformation code that works on both java8 and java9
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the TestDefineClass with
java -cp classes TestDefineClass
You need a minimal class org.example.Something.class and a minimal org.example.package-info.class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
loadClass: class org.example.Something
org.example
defineClass: class org.example.Something
org.example
ACTUAL -
loadClass: class org.example.Something
org.example
defineClass: class org.example.Something
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
public class TestDefineClass
{
private static final class TestLoader extends URLClassLoader
{
private TestLoader(URL[] urls)
{
super(urls,null);
}
public Class<?> testDefineClass(String name, byte[] b, int off, int len)
{
return defineClass(name,b,off,len);
}
@Override
public Package getPackage(String name)
{
// TODO Auto-generated method stub
return super.getPackage(name);
}
@Override
public Package[] getPackages()
{
// TODO Auto-generated method stub
return super.getPackages();
}
}
public static void main(String[] args) throws Exception
{
File classes = new File("./classes").getAbsoluteFile();
TestLoader loader = new TestLoader(new URL[] {classes.toURI().toURL()});
Class<?> c = loader.loadClass("org.example.Something");
System.err.println("loadClass: "+c);
Arrays.asList(loader.getPackages()).stream().map(Package::getName).filter(s->s.startsWith("org.")).forEach(System.err::println);
loader.close();
loader = new TestLoader(new URL[] {classes.toURI().toURL()});
File classfile = new File("./classes/org/example/Something.class");
int len=(int)classfile.length();
byte[] data = new byte[len];
try(InputStream in = new FileInputStream(classfile))
{
int pos=0;
while (pos<len)
pos += in.read(data,pos,len-pos);
}
c = loader.testDefineClass("org.example.Something",data,0,len);
System.err.println("defineClass: "+c);
Arrays.asList(loader.getPackages()).stream().map(Package::getName).filter(s->s.startsWith("org.")).forEach(System.err::println);
loader.close();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
run java 9
java version "1.8.0_152-ea"
Java(TM) SE Runtime Environment (build 1.8.0_152-ea-b05)
Java HotSpot(TM) 64-Bit Server VM (build 25.152-b05, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux pellet 4.10.0-35-generic #39-Ubuntu SMP Wed Sep 13 07:46:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
Calling defineClass(String name, byte[] b, int off, int len) loads the class but not any associated packages.
In Java9, the behaviour is that the package is loaded.
This makes it impossible to write class transformation code that works on both java8 and java9
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the TestDefineClass with
java -cp classes TestDefineClass
You need a minimal class org.example.Something.class and a minimal org.example.package-info.class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
loadClass: class org.example.Something
org.example
defineClass: class org.example.Something
org.example
ACTUAL -
loadClass: class org.example.Something
org.example
defineClass: class org.example.Something
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
public class TestDefineClass
{
private static final class TestLoader extends URLClassLoader
{
private TestLoader(URL[] urls)
{
super(urls,null);
}
public Class<?> testDefineClass(String name, byte[] b, int off, int len)
{
return defineClass(name,b,off,len);
}
@Override
public Package getPackage(String name)
{
// TODO Auto-generated method stub
return super.getPackage(name);
}
@Override
public Package[] getPackages()
{
// TODO Auto-generated method stub
return super.getPackages();
}
}
public static void main(String[] args) throws Exception
{
File classes = new File("./classes").getAbsoluteFile();
TestLoader loader = new TestLoader(new URL[] {classes.toURI().toURL()});
Class<?> c = loader.loadClass("org.example.Something");
System.err.println("loadClass: "+c);
Arrays.asList(loader.getPackages()).stream().map(Package::getName).filter(s->s.startsWith("org.")).forEach(System.err::println);
loader.close();
loader = new TestLoader(new URL[] {classes.toURI().toURL()});
File classfile = new File("./classes/org/example/Something.class");
int len=(int)classfile.length();
byte[] data = new byte[len];
try(InputStream in = new FileInputStream(classfile))
{
int pos=0;
while (pos<len)
pos += in.read(data,pos,len-pos);
}
c = loader.testDefineClass("org.example.Something",data,0,len);
System.err.println("defineClass: "+c);
Arrays.asList(loader.getPackages()).stream().map(Package::getName).filter(s->s.startsWith("org.")).forEach(System.err::println);
loader.close();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
run java 9