Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions proxy/proxy-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,9 @@

<profiles>
<profile>
<id>java9To25</id>
<id>java9To27</id>
<activation>
<jdk>(8,26)</jdk>
<jdk>(8,28)</jdk>
</activation>
<build>
<plugins>
Expand Down Expand Up @@ -256,9 +256,9 @@
</build>
</profile>
<profile>
<id>java25</id>
<id>java25To27</id>
<activation>
<jdk>25</jdk>
<jdk>(24,28)</jdk>
</activation>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,116 +24,34 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProxyUtils
{
private static Logger LOGGER = LoggerFactory.getLogger(ProxyUtils.class);
public static final int JAVA_CLASS_VERSION = new BigDecimal(System.getProperty("java.class.version")).intValue();
private static int weavingJavaVersion = -1; // initialise an invalid number
/**
* Utility class for proxy generation.
*/
public class ProxyUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ProxyUtils.class);
/**
* The Java class version of the current JVM.
*/
public static final int JAVA_CLASS_VERSION = new BigDecimal(System.getProperty("java.class.version")).intValue();
private static int weavingJavaVersion = -1; // initialise an invalid number

/**
* Get the class file version to be used for weaving.
*
* @return the class file version, e.g. 69 for Java 25
*/
public static int getWeavingJavaVersion() {
if (weavingJavaVersion == -1) {
weavingJavaVersion = verifyJavaClassVersion(JAVA_CLASS_VERSION);
}
return weavingJavaVersion;
}

/**
* Get the java version to be woven at.
* @return
*/
public static int getWeavingJavaVersion() {
if (weavingJavaVersion == -1 ) {
//In order to avoid an inconsistent stack error the version of the woven byte code needs to match
//the level of byte codes in the original class
switch(JAVA_CLASS_VERSION) {
case Opcodes.V25:
LOGGER.debug("Weaving to Java 25");
weavingJavaVersion = Opcodes.V25;
break;
case Opcodes.V24:
LOGGER.debug("Weaving to Java 24");
weavingJavaVersion = Opcodes.V24;
break;
case Opcodes.V23:
LOGGER.debug("Weaving to Java 23");
weavingJavaVersion = Opcodes.V23;
break;
case Opcodes.V22:
LOGGER.debug("Weaving to Java 22");
weavingJavaVersion = Opcodes.V22;
break;
case Opcodes.V21:
LOGGER.debug("Weaving to Java 21");
weavingJavaVersion = Opcodes.V21;
break;
case Opcodes.V20:
LOGGER.debug("Weaving to Java 20");
weavingJavaVersion = Opcodes.V20;
break;
case Opcodes.V19:
LOGGER.debug("Weaving to Java 19");
weavingJavaVersion = Opcodes.V19;
break;
case Opcodes.V18:
LOGGER.debug("Weaving to Java 18");
weavingJavaVersion = Opcodes.V18;
break;
case Opcodes.V17:
LOGGER.debug("Weaving to Java 17");
weavingJavaVersion = Opcodes.V17;
break;
case Opcodes.V16:
LOGGER.debug("Weaving to Java 16");
weavingJavaVersion = Opcodes.V16;
break;
case Opcodes.V15:
LOGGER.debug("Weaving to Java 15");
weavingJavaVersion = Opcodes.V15;
break;
case Opcodes.V14:
LOGGER.debug("Weaving to Java 14");
weavingJavaVersion = Opcodes.V14;
break;
case Opcodes.V13:
LOGGER.debug("Weaving to Java 13");
weavingJavaVersion = Opcodes.V13;
break;
case Opcodes.V12:
LOGGER.debug("Weaving to Java 12");
weavingJavaVersion = Opcodes.V12;
break;
case Opcodes.V11:
LOGGER.debug("Weaving to Java 11");
weavingJavaVersion = Opcodes.V11;
break;
case Opcodes.V10:
LOGGER.debug("Weaving to Java 10");
weavingJavaVersion = Opcodes.V10;
break;
case Opcodes.V9:
LOGGER.debug("Weaving to Java 9");
weavingJavaVersion = Opcodes.V9;
break;
case Opcodes.V1_8:
LOGGER.debug("Weaving to Java 8");
weavingJavaVersion = Opcodes.V1_8;
break;
case Opcodes.V1_7:
LOGGER.debug("Weaving to Java 7");
weavingJavaVersion = Opcodes.V1_7;
break;
case Opcodes.V1_6:
LOGGER.debug("Weaving to Java 6");
weavingJavaVersion = Opcodes.V1_6;
break;
case Opcodes.V1_5:
LOGGER.debug("Weaving to Java 5");
weavingJavaVersion = Opcodes.V1_5;
break;
default:
if (JAVA_CLASS_VERSION > Opcodes.V25) {
// newer JVMs load older class files, so generate proxies at the highest level we know
LOGGER.debug("Weaving to Java 25 on newer Java class version {}", JAVA_CLASS_VERSION);
weavingJavaVersion = Opcodes.V25;
break;
}
//aries should work with Java 5 or above
throw new IllegalArgumentException("Invalid Java version " + JAVA_CLASS_VERSION);
}
}
return weavingJavaVersion;
}
static int verifyJavaClassVersion(int javaClassVersion) {
if (javaClassVersion < Opcodes.V1_8 || javaClassVersion == Opcodes.V1_1) {
throw new IllegalArgumentException("Unsupported Java class version: " + javaClassVersion);
}
LOGGER.debug("Weaving to Java {}", javaClassVersion - Opcodes.V1_8 + 8);
return javaClassVersion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,6 @@ public abstract class AbstractWovenProxyAdapter extends ClassVisitor implements

protected boolean currentMethodDeclaringTypeIsInterface;


public static final boolean IS_AT_LEAST_JAVA_6 = JAVA_CLASS_VERSION >= Opcodes.V1_6;

/**
* Create a new adapter for the supplied class
*
Expand Down Expand Up @@ -240,7 +237,7 @@ public final void visit(int version, int access, String name, String signature,
Arrays.asList(interfaces).contains(Type.getInternalName(Serializable.class)) ||
checkInterfacesForSerializability(interfaces);

if (!!!WovenProxy.class.isAssignableFrom(superClass)) {
if (!WovenProxy.class.isAssignableFrom(superClass)) {

// We have found a type we need to add WovenProxy information to

Expand Down Expand Up @@ -298,7 +295,7 @@ private void cannotLoadSuperClassException(String superName, UnableToProxyExcept
* initialization references the subclass being woven. Odd, but seen
* in the wild!
*/
private final boolean superHasNoArgsConstructor(String superName, String name) {
private boolean superHasNoArgsConstructor(String superName, String name) {

ConstructorFinder cf = new ConstructorFinder();

Expand Down Expand Up @@ -347,8 +344,8 @@ public final MethodVisitor visitMethod(int access, String name, String desc,
// Only weave "real" instance methods. Not constructors, initializers or
// compiler generated ones.
if ((access & (ACC_STATIC | ACC_PRIVATE | ACC_SYNTHETIC
| ACC_NATIVE | ACC_BRIDGE)) == 0 && !!!name.equals("<init>") &&
!!!name.equals("<clinit>")) {
| ACC_NATIVE | ACC_BRIDGE)) == 0 && !name.equals("<init>") &&
!name.equals("<clinit>")) {

// found a method we should weave

Expand Down Expand Up @@ -449,7 +446,7 @@ protected abstract MethodVisitor getWeavingMethodVisitor(int access, String name
/**
* Write the methods we need for wovenProxies on the highest supertype
*/
private final void writeFinalWovenProxyMethods() {
private void writeFinalWovenProxyMethods() {
// add private fields for the Callable<Object> dispatcher
// and InvocationListener. These aren't static because we can have
// multiple instances of the same proxy class. These should not be
Expand Down Expand Up @@ -519,7 +516,7 @@ private final void writeFinalWovenProxyMethods() {
* overridden on each class, we also write a constructor for this method to
* use if we don't have one.
*/
private final void writeCreateNewProxyInstanceAndConstructor() {
private void writeCreateNewProxyInstanceAndConstructor() {
GeneratorAdapter methodAdapter = getMethodGenerator(ACC_PUBLIC, new Method(
"org_apache_aries_proxy_weaving_WovenProxy_createNewProxyInstance",
WOVEN_PROXY_IFACE_TYPE, DISPATCHER_LISTENER_METHOD_ARGS));
Expand Down Expand Up @@ -557,7 +554,7 @@ private final void writeCreateNewProxyInstanceAndConstructor() {
methodAdapter.invokeConstructor(typeBeingWoven, NO_ARGS_CONSTRUCTOR);
else
throw new RuntimeException(new UnableToProxyException(typeBeingWoven.getClassName(),
String.format("The class %s and its superclass %s do not have no-args constructors and cannot be woven.",
format("The class %s and its superclass %s do not have no-args constructors and cannot be woven.",
typeBeingWoven.getClassName(), superType.getClassName())));
}
methodAdapter.loadThis();
Expand Down Expand Up @@ -594,7 +591,7 @@ private final void writeCreateNewProxyInstanceAndConstructor() {
* Create fields and an initialiser for {@link java.lang.reflect.Method}
* objects in our class
*/
private final void writeStaticInitMethod() {
private void writeStaticInitMethod() {
// we create a static field for each method we encounter with a *unique*
// random name
// since each method needs to be stored individually
Expand Down Expand Up @@ -704,7 +701,7 @@ public static void readClass(Class<?> c, ClassVisitor adapter) throws IOExceptio
* @param fieldName
* @param fieldDescriptor
*/
private final void generateField(String fieldName, String fieldDescriptor) {
private void generateField(String fieldName, String fieldDescriptor) {
FieldVisitor fv = cv.visitField(ACC_PROTECTED | ACC_TRANSIENT | ACC_SYNTHETIC
| ACC_FINAL, fieldName, fieldDescriptor, null, null);
for (String s : annotationTypeDescriptors)
Expand All @@ -719,7 +716,7 @@ private final void generateField(String fieldName, String fieldDescriptor) {
* @param methodSignature
* @return
*/
private final GeneratorAdapter getMethodGenerator(int access, Method method) {
private GeneratorAdapter getMethodGenerator(int access, Method method) {
access = access | ACC_SYNTHETIC;
GeneratorAdapter ga = new GeneratorAdapter(access, method, null, null, cv);
for (String s : annotationTypeDescriptors)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import static org.objectweb.asm.Opcodes.ACC_ENUM;
import static org.objectweb.asm.Opcodes.ACC_INTERFACE;

import org.apache.aries.proxy.impl.common.AbstractWovenProxyAdapter;
import org.apache.aries.proxy.impl.common.OSGiFriendlyClassVisitor;
import org.apache.aries.proxy.impl.common.OSGiFriendlyClassWriter;
import org.objectweb.asm.ClassReader;
Expand All @@ -34,24 +33,20 @@
*/
public final class WovenProxyGenerator
{
public static final byte[] getWovenProxy(byte[] original, ClassLoader loader){
public static byte[] getWovenProxy(byte[] original, ClassLoader loader){
ClassReader cReader = new ClassReader(original);
//Don't weave interfaces, enums or annotations
if((cReader.getAccess() & (ACC_INTERFACE | ACC_ANNOTATION | ACC_ENUM)) != 0)
return null;

//If we are Java 1.6 + compiled then we need to compute stack frames, otherwise
//maxs are fine (and faster)
int computeVal = AbstractWovenProxyAdapter.IS_AT_LEAST_JAVA_6 ?
ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS;
int computeVal = ClassWriter.COMPUTE_FRAMES;
ClassWriter cWriter = new OSGiFriendlyClassWriter(cReader, computeVal, loader);
ClassVisitor cv = new OSGiFriendlyClassVisitor(cWriter, computeVal );
//Wrap our outer layer to add the original SerialVersionUID if it was previously being defaulted
ClassVisitor weavingAdapter = new SyntheticSerialVerUIDAdder(
new WovenProxyAdapter(cv, cReader.getClassName(), loader));

// If we are Java 1.6 + then we need to skip frames as they will be recomputed
cReader.accept(weavingAdapter, AbstractWovenProxyAdapter.IS_AT_LEAST_JAVA_6 ? ClassReader.SKIP_FRAMES : 0);
cReader.accept(weavingAdapter, ClassReader.SKIP_FRAMES);

return cWriter.toByteArray();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.proxy.impl;

import org.objectweb.asm.Opcodes;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

public class ProxyUtilsTest {
@Test
public void testVerifyJavaClassVersion8AndAbove() {
assertEquals(Opcodes.V1_8, ProxyUtils.verifyJavaClassVersion(52));
assertEquals(Opcodes.V9, ProxyUtils.verifyJavaClassVersion(53));
assertEquals(Opcodes.V10, ProxyUtils.verifyJavaClassVersion(54));
assertEquals(Opcodes.V11, ProxyUtils.verifyJavaClassVersion(55));
assertEquals(Opcodes.V12, ProxyUtils.verifyJavaClassVersion(56));
assertEquals(Opcodes.V13, ProxyUtils.verifyJavaClassVersion(57));
assertEquals(Opcodes.V14, ProxyUtils.verifyJavaClassVersion(58));
assertEquals(Opcodes.V15, ProxyUtils.verifyJavaClassVersion(59));
assertEquals(Opcodes.V16, ProxyUtils.verifyJavaClassVersion(60));
assertEquals(Opcodes.V17, ProxyUtils.verifyJavaClassVersion(61));
assertEquals(Opcodes.V18, ProxyUtils.verifyJavaClassVersion(62));
assertEquals(Opcodes.V19, ProxyUtils.verifyJavaClassVersion(63));
assertEquals(Opcodes.V20, ProxyUtils.verifyJavaClassVersion(64));
assertEquals(Opcodes.V21, ProxyUtils.verifyJavaClassVersion(65));
assertEquals(Opcodes.V22, ProxyUtils.verifyJavaClassVersion(66));
assertEquals(Opcodes.V23, ProxyUtils.verifyJavaClassVersion(67));
assertEquals(Opcodes.V24, ProxyUtils.verifyJavaClassVersion(68));
assertEquals(Opcodes.V25, ProxyUtils.verifyJavaClassVersion(69));
assertEquals(Opcodes.V26, ProxyUtils.verifyJavaClassVersion(70));
assertEquals(Opcodes.V27, ProxyUtils.verifyJavaClassVersion(71));
assertEquals(72, ProxyUtils.verifyJavaClassVersion(72)); // supporting future versions of Java we don't know about yet
}

@Test
public void testVerifyJavaClassVersionBelow8() {
int V1_0 = 45; // there is no Opcodes.V1_0 constant in ASM
for (int i = V1_0; i < Opcodes.V1_8; i++) {
int javaClassVersion = i;
assertThrows(IllegalArgumentException.class, () -> ProxyUtils.verifyJavaClassVersion(javaClassVersion));
}
// special case for V1_1 which is 196653
assertThrows(IllegalArgumentException.class, () -> ProxyUtils.verifyJavaClassVersion(Opcodes.V1_1));
}
}
2 changes: 1 addition & 1 deletion proxy/proxy-itests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
<profile>
<id>java9To25</id>
<activation>
<jdk>(8,26)</jdk>
<jdk>(8,28)</jdk>
</activation>
<build>
<plugins>
Expand Down
Loading