ACC_SUPER简介

class文件中的access flag记录了一个类的相关信息,比如public abstract final等等。其中有一个值ACC_SUPER。现理解如下:
ACC_SUPER是用来表示如何调用父类的方法。在jdk1.1之前,jvm使用一种invokenonvirtual的指令,调用父类方法。这个方法就是现在的invokespecial 前身。既然连名字都改过了,他们的实现差距可以认为已经比较大了。invokenonvirtual是不会进行虚函数查找的,也就是总是静态绑定。
我们知道,在class文件中使用CONSTANT_Methodref_info来表示一个方法。CONSTANT_Methodref_info中有一个指向类的成员,invokenonvirtual会直接使用CONSTANT_Methodref_info中的类进行方法调用,而不去进行虚函数查找。因此,需要由编译器在编译时就绑定到最近的父类。jdk1.1以后,jvm会忽略CONSTANT_Methodref_info 中的class,转而去查找最近的超类方法。
这个改动是非常有意义的,我们来一下下面的代码:
有一个组件A

public class GrandParent {
  protected void myMethod() {
    // ...
  }
}
public class Parent extends GrandParent {
}


组件B使用了组件A

public class Child extends Parent {
  protected void myMethod() {
    // ...
    super.myMethod();
  }
}


很明显,组件B肯定是用了GrandParent.myMethod()。因为Parent里没有myMethod方法。但是,如果你更新了组件A

public class GrandParent {
  protected void myMethod() {
    // ...
  }
}
public class Parent extends GrandParent {
  protected void myMethod() {
    // ...
    super.myMethod();
  }
}


这个时候,如果使用invokenonvirtual调用方式,你依然会运行GrandParent.myMethod()(在不重新编译Child的情况下)。因为这是在编译时绑定的。使用了CONSTANT_Methodref_info里的class作为调用基准。这个结果显然不是你想看到的。
但如果使用了新的invokespecial ,他就会搜索类层次,找到最近的一个父类进行方法调用,得到正确的结果。第2中方法就是设置了ACC_SUPER时的情况。
现在编译器都会生成ACC_SUPER以支持一个正确的父类调用。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
详细解释代码import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms from torch.utils.data import DataLoader # 图像预处理 transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) # 加载数据集 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = DataLoader(trainset, batch_size=128, shuffle=True, num_workers=0) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = DataLoader(testset, batch_size=128, shuffle=False, num_workers=0) # 构建模型 class RNNModel(nn.Module): def init(self): super(RNNModel, self).init() self.rnn = nn.RNN(input_size=3072, hidden_size=512, num_layers=2, batch_first=True) self.fc = nn.Linear(512, 10) def forward(self, x): # 将输入数据reshape成(batch_size, seq_len, feature_dim) x = x.view(-1, 3072, 1).transpose(1, 2) x, _ = self.rnn(x) x = x[:, -1, :] x = self.fc(x) return x net = RNNModel() # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(net.parameters(), lr=0.001) # 训练模型 loss_list = [] acc_list = [] for epoch in range(30): # 多批次循环 running_loss = 0.0 correct = 0 total = 0 for i, data in enumerate(trainloader, 0): # 获取输入 inputs, labels = data # 梯度清零 optimizer.zero_grad() # 前向传播,反向传播,优化 outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # 打印统计信息 running_loss += loss.item() _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() acc = 100 * correct / total acc_list.append(acc) loss_list.append(running_loss / len(trainloader)) print('[%d] loss: %.3f, acc: %.3f' % (epoch + 1, running_loss / len(trainloader), acc)) print('Finished Training') torch.save(net.state_dict(), 'rnn1.pt') # 绘制loss变化曲线和准确率变化曲线 import matplotlib.pyplot as plt fig, axs = plt.subplots(2, 1, figsize=(10, 10)) axs[0].plot(loss_list) axs[0].set_title("Training Loss") axs[0].set_xlabel("Epoch") axs[0].set_ylabel("Loss") axs[1].plot(acc_list) axs[1].set_title("Training Accuracy") axs[1].set_xlabel("Epoch") axs[1].set_ylabel("Accuracy") plt.show() # 测试模型 correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))
最新发布
05-27
这段代码是一个基于RNN(循环神经网络)的模型来对CIFAR-10数据集进行分类。以下是详细的解释: 1. 导入需要的库: ``` import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms from torch.utils.data import DataLoader ``` 2. 图像预处理: ``` transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) ``` 这里使用了transforms.Compose()函数来将多个预处理操作组合在一起。首先将图像转换成张量,然后进行归一化,使其值在[-1,1]之间。 3. 加载数据集: ``` trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = DataLoader(trainset, batch_size=128, shuffle=True, num_workers=0) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = DataLoader(testset, batch_size=128, shuffle=False, num_workers=0) ``` 这里使用了torchvision.datasets.CIFAR10()函数来加载CIFAR-10数据集,train=True表示加载训练集,train=False表示加载测试集。通过DataLoader()函数将数据集转换成一个可迭代的对象,可以方便地进行批处理、数据增强等操作。 4. 构建模型: ``` class RNNModel(nn.Module): def __init__(self): super(RNNModel, self).__init__() self.rnn = nn.RNN(input_size=3072, hidden_size=512, num_layers=2, batch_first=True) self.fc = nn.Linear(512, 10) def forward(self, x): x = x.view(-1, 3072, 1).transpose(1, 2) x, _ = self.rnn(x) x = x[:, -1, :] x = self.fc(x) return x net = RNNModel() ``` 这里定义了一个RNNModel类,它继承了nn.Module类。在__init__()方法中,我们定义了一个RNN层和一个全连接层来构建模型。在forward()方法中,我们首先将输入数据reshape成(batch_size, seq_len, feature_dim)的形状,然后经过RNN层得到输出,最后经过全连接层得到最终的分类结果。 5. 定义损失函数和优化器: ``` criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(net.parameters(), lr=0.001) ``` 这里使用交叉熵损失函数和Adam优化器来训练模型。 6. 训练模型: ``` loss_list = [] acc_list = [] for epoch in range(30): running_loss = 0.0 correct = 0 total =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值